PageSourceSearch

https://dergipark.org.tr/zollu/keen/vendors/global/vendors.bundle.js

js dergipark.org.tr collected 2026-09-24 08:29:45 UTC 3,798,263 bytes, 81,694 lines download raw bytes

vendor: 9,492 bytes, lines 1-385
1/*!
2 * jQuery JavaScript Library v3.4.1
3 * https://jquery.com/
4 *
5 * Includes Sizzle.js
6 * https://sizzlejs.com/
7 *
8 * Copyright JS Foundation and other contributors
9 * Released under the MIT license
10 * https://jquery.org/license
11 *
12 * Date: 2019-05-01T21:04Z
13 */
14( function( global, factory ) {
15
16	"use strict";
17
18	if ( typeof module === "object" && typeof module.exports === "object" ) {
19
20		// For CommonJS and CommonJS-like environments where a proper `window`
21		// is present, execute the factory and get jQuery.
22		// For environments that do not have a `window` with a `document`
23		// (such as Node.js), expose a factory as module.exports.
24		// This accentuates the need for the creation of a real `window`.
25		// e.g. var jQuery = require("jquery")(window);
26		// See ticket #14549 for more info.
27		module.exports = global.document ?
28			factory( global, true ) :
29			function( w ) {
30				if ( !w.document ) {
31					throw new Error( "jQuery requires a window with a document" );
32				}
33				return factory( w );
34			};
35	} else {
36		factory( global );
37	}
38
39// Pass this if window is not defined yet
40} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
41
42// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
43// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
44// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
45// enough that all such attempts are guarded in a try block.
46"use strict";
47
48var arr = [];
49
50var document = window.document;
51
52var getProto = Object.getPrototypeOf;
53
54var slice = arr.slice;
55
56var concat = arr.concat;
57
58var push = arr.push;
59
60var indexOf = arr.indexOf;
61
62var class2type = {};
63
64var toString = class2type.toString;
65
66var hasOwn = class2type.hasOwnProperty;
67
68var fnToString = hasOwn.toString;
69
70var ObjectFunctionString = fnToString.call( Object );
71
72var support = {};
73
74var isFunction = function isFunction( obj ) {
75
76      // Support: Chrome <=57, Firefox <=52
77      // In some browsers, typeof returns "function" for HTML <object> elements
78      // (i.e., `typeof document.createElement( "object" ) === "function"`).
79      // We don't want to classify *any* DOM node as a function.
80      return typeof obj === "function" && typeof obj.nodeType !== "number";
81  };
82
83
84var isWindow = function isWindow( obj ) {
85		return obj != null && obj === obj.window;
86	};
87
88
89
90
91	var preservedScriptAttributes = {
92		type: true,
93		src: true,
94		nonce: true,
95		noModule: true
96	};
97
98	function DOMEval( code, node, doc ) {
99		doc = doc || document;
100
101		var i, val,
102			script = doc.createElement( "script" );
103
104		script.text = code;
105		if ( node ) {
106			for ( i in preservedScriptAttributes ) {
107
108				// Support: Firefox 64+, Edge 18+
109				// Some browsers don't support the "nonce" property on scripts.
110				// On the other hand, just using `getAttribute` is not enough as
111				// the `nonce` attribute is reset to an empty string whenever it
112				// becomes browsing-context connected.
113				// See https://github.com/whatwg/html/issues/2369
114				// See https://html.spec.whatwg.org/#nonce-attributes
115				// The `node.getAttribute` check was added for the sake of
116				// `jQuery.globalEval` so that it can fake a nonce-containing node
117				// via an object.
118				val = node[ i ] || node.getAttribute && node.getAttribute( i );
119				if ( val ) {
120					script.setAttribute( i, val );
121				}
122			}
123		}
124		doc.head.appendChild( script ).parentNode.removeChild( script );
125	}
126
127
128function toType( obj ) {
129	if ( obj == null ) {
130		return obj + "";
131	}
132
133	// Support: Android <=2.3 only (functionish RegExp)
134	return typeof obj === "object" || typeof obj === "function" ?
135		class2type[ toString.call( obj ) ] || "object" :
136		typeof obj;
137}
138/* global Symbol */
139// Defining this global in .eslintrc.json would create a danger of using the global
140// unguarded in another place, it seems safer to define global only for this module
141
142
143
144var
145	version = "3.4.1",
146
147	// Define a local copy of jQuery
148	jQuery = function( selector, context ) {
149
150		// The jQuery object is actually just the init constructor 'enhanced'
151		// Need init if jQuery is called (just allow error to be thrown if not included)
152		return new jQuery.fn.init( selector, context );
153	},
154
155	// Support: Android <=4.0 only
156	// Make sure we trim BOM and NBSP
157	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
158
159jQuery.fn = jQuery.prototype = {
160
161	// The current version of jQuery being used
162	jquery: version,
163
164	constructor: jQuery,
165
166	// The default length of a jQuery object is 0
167	length: 0,
168
169	toArray: function() {
170		return slice.call( this );
171	},
172
173	// Get the Nth element in the matched element set OR
174	// Get the whole matched element set as a clean array
175	get: function( num ) {
176
177		// Return all the elements in a clean array
178		if ( num == null ) {
179			return slice.call( this );
180		}
181
182		// Return just the one element from the set
183		return num < 0 ? this[ num + this.length ] : this[ num ];
184	},
185
186	// Take an array of elements and push it onto the stack
187	// (returning the new matched element set)
188	pushStack: function( elems ) {
189
190		// Build a new jQuery matched element set
191		var ret = jQuery.merge( this.constructor(), elems );
192
193		// Add the old object onto the stack (as a reference)
194		ret.prevObject = this;
195
196		// Return the newly-formed element set
197		return ret;
198	},
199
200	// Execute a callback for every element in the matched set.
201	each: function( callback ) {
202		return jQuery.each( this, callback );
203	},
204
205	map: function( callback ) {
206		return this.pushStack( jQuery.map( this, function( elem, i ) {
207			return callback.call( elem, i, elem );
208		} ) );
209	},
210
211	slice: function() {
212		return this.pushStack( slice.apply( this, arguments ) );
213	},
214
215	first: function() {
216		return this.eq( 0 );
217	},
218
219	last: function() {
220		return this.eq( -1 );
221	},
222
223	eq: function( i ) {
224		var len = this.length,
225			j = +i + ( i < 0 ? len : 0 );
226		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
227	},
228
229	end: function() {
230		return this.prevObject || this.constructor();
231	},
232
233	// For internal use only.
234	// Behaves like an Array's method, not like a jQuery method.
235	push: push,
236	sort: arr.sort,
237	splice: arr.splice
238};
239
240jQuery.extend = jQuery.fn.extend = function() {
241	var options, name, src, copy, copyIsArray, clone,
242		target = arguments[ 0 ] || {},
243		i = 1,
244		length = arguments.length,
245		deep = false;
246
247	// Handle a deep copy situation
248	if ( typeof target === "boolean" ) {
249		deep = target;
250
251		// Skip the boolean and the target
252		target = arguments[ i ] || {};
253		i++;
254	}
255
256	// Handle case when target is a string or something (possible in deep copy)
257	if ( typeof target !== "object" && !isFunction( target ) ) {
258		target = {};
259	}
260
261	// Extend jQuery itself if only one argument is passed
262	if ( i === length ) {
263		target = this;
264		i--;
265	}
266
267	for ( ; i < length; i++ ) {
268
269		// Only deal with non-null/undefined values
270		if ( ( options = arguments[ i ] ) != null ) {
271
272			// Extend the base object
273			for ( name in options ) {
274				copy = options[ name ];
275
276				// Prevent Object.prototype pollution
277				// Prevent never-ending loop
278				if ( name === "__proto__" || target === copy ) {
279					continue;
280				}
281
282				// Recurse if we're merging plain objects or arrays
283				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
284					( copyIsArray = Array.isArray( copy ) ) ) ) {
285					src = target[ name ];
286
287					// Ensure proper type for the source value
288					if ( copyIsArray && !Array.isArray( src ) ) {
289						clone = [];
290					} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
291						clone = {};
292					} else {
293						clone = src;
294					}
295					copyIsArray = false;
296
297					// Never move original objects, clone them
298					target[ name ] = jQuery.extend( deep, clone, copy );
299
300				// Don't bring in undefined values
301				} else if ( copy !== undefined ) {
302					target[ name ] = copy;
303				}
304			}
305		}
306	}
307
308	// Return the modified object
309	return target;
310};
311
312jQuery.extend( {
313
314	// Unique for each copy of jQuery on the page
315	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
316
317	// Assume jQuery is ready without the ready module
318	isReady: true,
319
320	error: function( msg ) {
321		throw new Error( msg );
322	},
323
324	noop: function() {},
325
326	isPlainObject: function( obj ) {
327		var proto, Ctor;
328
329		// Detect obvious negatives
330		// Use toString instead of jQuery.type to catch host objects
331		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
332			return false;
333		}
334
335		proto = getProto( obj );
336
337		// Objects with no prototype (e.g., `Object.create( null )`) are plain
338		if ( !proto ) {
339			return true;
340		}
341
342		// Objects with prototype are plain iff they were constructed by a global Object function
343		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
344		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
345	},
346
347	isEmptyObject: function( obj ) {
348		var name;
349
350		for ( name in obj ) {
351			return false;
352		}
353		return true;
354	},
355
356	// Evaluates a script in a global context
357	globalEval: function( code, options ) {
358		DOMEval( code, { nonce: options && options.nonce } );
359	},
360
361	each: function( obj, callback ) {
362		var length, i = 0;
363
364		if ( isArrayLike( obj ) ) {
365			length = obj.length;
366			for ( ; i < length; i++ ) {
367				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
368					break;
369				}
370			}
371		} else {
372			for ( i in obj ) {
373				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
374					break;
375				}
376			}
377		}
378
379		return obj;
380	},
381
382	// Support: Android <=4.0 only
383	trim: function( text ) {
384		return text == null ?
385			"" :
vendor: 14,126 bytes, lines 386-904
386			( text + "" ).replace( rtrim, "" );
387	},
388
389	// results is for internal usage only
390	makeArray: function( arr, results ) {
391		var ret = results || [];
392
393		if ( arr != null ) {
394			if ( isArrayLike( Object( arr ) ) ) {
395				jQuery.merge( ret,
396					typeof arr === "string" ?
397					[ arr ] : arr
398				);
399			} else {
400				push.call( ret, arr );
401			}
402		}
403
404		return ret;
405	},
406
407	inArray: function( elem, arr, i ) {
408		return arr == null ? -1 : indexOf.call( arr, elem, i );
409	},
410
411	// Support: Android <=4.0 only, PhantomJS 1 only
412	// push.apply(_, arraylike) throws on ancient WebKit
413	merge: function( first, second ) {
414		var len = +second.length,
415			j = 0,
416			i = first.length;
417
418		for ( ; j < len; j++ ) {
419			first[ i++ ] = second[ j ];
420		}
421
422		first.length = i;
423
424		return first;
425	},
426
427	grep: function( elems, callback, invert ) {
428		var callbackInverse,
429			matches = [],
430			i = 0,
431			length = elems.length,
432			callbackExpect = !invert;
433
434		// Go through the array, only saving the items
435		// that pass the validator function
436		for ( ; i < length; i++ ) {
437			callbackInverse = !callback( elems[ i ], i );
438			if ( callbackInverse !== callbackExpect ) {
439				matches.push( elems[ i ] );
440			}
441		}
442
443		return matches;
444	},
445
446	// arg is for internal usage only
447	map: function( elems, callback, arg ) {
448		var length, value,
449			i = 0,
450			ret = [];
451
452		// Go through the array, translating each of the items to their new values
453		if ( isArrayLike( elems ) ) {
454			length = elems.length;
455			for ( ; i < length; i++ ) {
456				value = callback( elems[ i ], i, arg );
457
458				if ( value != null ) {
459					ret.push( value );
460				}
461			}
462
463		// Go through every key on the object,
464		} else {
465			for ( i in elems ) {
466				value = callback( elems[ i ], i, arg );
467
468				if ( value != null ) {
469					ret.push( value );
470				}
471			}
472		}
473
474		// Flatten any nested arrays
475		return concat.apply( [], ret );
476	},
477
478	// A global GUID counter for objects
479	guid: 1,
480
481	// jQuery.support is not used in Core but other projects attach their
482	// properties to it so it needs to exist.
483	support: support
484} );
485
486if ( typeof Symbol === "function" ) {
487	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
488}
489
490// Populate the class2type map
491jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
492function( i, name ) {
493	class2type[ "[object " + name + "]" ] = name.toLowerCase();
494} );
495
496function isArrayLike( obj ) {
497
498	// Support: real iOS 8.2 only (not reproducible in simulator)
499	// `in` check used to prevent JIT error (gh-2145)
500	// hasOwn isn't used here due to false negatives
501	// regarding Nodelist length in IE
502	var length = !!obj && "length" in obj && obj.length,
503		type = toType( obj );
504
505	if ( isFunction( obj ) || isWindow( obj ) ) {
506		return false;
507	}
508
509	return type === "array" || length === 0 ||
510		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
511}
512var Sizzle =
513/*!
514 * Sizzle CSS Selector Engine v2.3.4
515 * https://sizzlejs.com/
516 *
517 * Copyright JS Foundation and other contributors
518 * Released under the MIT license
519 * https://js.foundation/
520 *
521 * Date: 2019-04-08
522 */
523(function( window ) {
524
525var i,
526	support,
527	Expr,
528	getText,
529	isXML,
530	tokenize,
531	compile,
532	select,
533	outermostContext,
534	sortInput,
535	hasDuplicate,
536
537	// Local document vars
538	setDocument,
539	document,
540	docElem,
541	documentIsHTML,
542	rbuggyQSA,
543	rbuggyMatches,
544	matches,
545	contains,
546
547	// Instance-specific data
548	expando = "sizzle" + 1 * new Date(),
549	preferredDoc = window.document,
550	dirruns = 0,
551	done = 0,
552	classCache = createCache(),
553	tokenCache = createCache(),
554	compilerCache = createCache(),
555	nonnativeSelectorCache = createCache(),
556	sortOrder = function( a, b ) {
557		if ( a === b ) {
558			hasDuplicate = true;
559		}
560		return 0;
561	},
562
563	// Instance methods
564	hasOwn = ({}).hasOwnProperty,
565	arr = [],
566	pop = arr.pop,
567	push_native = arr.push,
568	push = arr.push,
569	slice = arr.slice,
570	// Use a stripped-down indexOf as it's faster than native
571	// https://jsperf.com/thor-indexof-vs-for/5
572	indexOf = function( list, elem ) {
573		var i = 0,
574			len = list.length;
575		for ( ; i < len; i++ ) {
576			if ( list[i] === elem ) {
577				return i;
578			}
579		}
580		return -1;
581	},
582
583	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
584
585	// Regular expressions
586
587	// http://www.w3.org/TR/css3-selectors/#whitespace
588	whitespace = "[\\x20\\t\\r\\n\\f]",
589
590	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
591	identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
592
593	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
594	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
595		// Operator (capture 2)
596		"*([*^$|!~]?=)" + whitespace +
597		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
598		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
599		"*\\]",
600
601	pseudos = ":(" + identifier + ")(?:\\((" +
602		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
603		// 1. quoted (capture 3; capture 4 or capture 5)
604		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
605		// 2. simple (capture 6)
606		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
607		// 3. anything else (capture 2)
608		".*" +
609		")\\)|)",
610
611	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
612	rwhitespace = new RegExp( whitespace + "+", "g" ),
613	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
614
615	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
616	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
617	rdescend = new RegExp( whitespace + "|>" ),
618
619	rpseudo = new RegExp( pseudos ),
620	ridentifier = new RegExp( "^" + identifier + "$" ),
621
622	matchExpr = {
623		"ID": new RegExp( "^#(" + identifier + ")" ),
624		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
625		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
626		"ATTR": new RegExp( "^" + attributes ),
627		"PSEUDO": new RegExp( "^" + pseudos ),
628		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
629			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
630			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
631		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
632		// For use in libraries implementing .is()
633		// We use this for POS matching in `select`
634		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
635			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
636	},
637
638	rhtml = /HTML$/i,
639	rinputs = /^(?:input|select|textarea|button)$/i,
640	rheader = /^h\d$/i,
641
642	rnative = /^[^{]+\{\s*\[native \w/,
643
644	// Easily-parseable/retrievable ID or TAG or CLASS selectors
645	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
646
647	rsibling = /[+~]/,
648
649	// CSS escapes
650	// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
651	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
652	funescape = function( _, escaped, escapedWhitespace ) {
653		var high = "0x" + escaped - 0x10000;
654		// NaN means non-codepoint
655		// Support: Firefox<24
656		// Workaround erroneous numeric interpretation of +"0x"
657		return high !== high || escapedWhitespace ?
658			escaped :
659			high < 0 ?
660				// BMP codepoint
661				String.fromCharCode( high + 0x10000 ) :
662				// Supplemental Plane codepoint (surrogate pair)
663				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
664	},
665
666	// CSS string/identifier serialization
667	// https://drafts.csswg.org/cssom/#common-serializing-idioms
668	rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
669	fcssescape = function( ch, asCodePoint ) {
670		if ( asCodePoint ) {
671
672			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
673			if ( ch === "\0" ) {
674				return "\uFFFD";
675			}
676
677			// Control characters and (dependent upon position) numbers get escaped as code points
678			return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
679		}
680
681		// Other potentially-special ASCII characters get backslash-escaped
682		return "\\" + ch;
683	},
684
685	// Used for iframes
686	// See setDocument()
687	// Removing the function wrapper causes a "Permission Denied"
688	// error in IE
689	unloadHandler = function() {
690		setDocument();
691	},
692
693	inDisabledFieldset = addCombinator(
694		function( elem ) {
695			return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
696		},
697		{ dir: "parentNode", next: "legend" }
698	);
699
700// Optimize for push.apply( _, NodeList )
701try {
702	push.apply(
703		(arr = slice.call( preferredDoc.childNodes )),
704		preferredDoc.childNodes
705	);
706	// Support: Android<4.0
707	// Detect silently failing push.apply
708	arr[ preferredDoc.childNodes.length ].nodeType;
709} catch ( e ) {
710	push = { apply: arr.length ?
711
712		// Leverage slice if possible
713		function( target, els ) {
714			push_native.apply( target, slice.call(els) );
715		} :
716
717		// Support: IE<9
718		// Otherwise append directly
719		function( target, els ) {
720			var j = target.length,
721				i = 0;
722			// Can't trust NodeList.length
723			while ( (target[j++] = els[i++]) ) {}
724			target.length = j - 1;
725		}
726	};
727}
728
729function Sizzle( selector, context, results, seed ) {
730	var m, i, elem, nid, match, groups, newSelector,
731		newContext = context && context.ownerDocument,
732
733		// nodeType defaults to 9, since context defaults to document
734		nodeType = context ? context.nodeType : 9;
735
736	results = results || [];
737
738	// Return early from calls with invalid selector or context
739	if ( typeof selector !== "string" || !selector ||
740		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
741
742		return results;
743	}
744
745	// Try to shortcut find operations (as opposed to filters) in HTML documents
746	if ( !seed ) {
747
748		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
749			setDocument( context );
750		}
751		context = context || document;
752
753		if ( documentIsHTML ) {
754
755			// If the selector is sufficiently simple, try using a "get*By*" DOM method
756			// (excepting DocumentFragment context, where the methods don't exist)
757			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
758
759				// ID selector
760				if ( (m = match[1]) ) {
761
762					// Document context
763					if ( nodeType === 9 ) {
764						if ( (elem = context.getElementById( m )) ) {
765
766							// Support: IE, Opera, Webkit
767							// TODO: identify versions
768							// getElementById can match elements by name instead of ID
769							if ( elem.id === m ) {
770								results.push( elem );
771								return results;
772							}
773						} else {
774							return results;
775						}
776
777					// Element context
778					} else {
779
780						// Support: IE, Opera, Webkit
781						// TODO: identify versions
782						// getElementById can match elements by name instead of ID
783						if ( newContext && (elem = newContext.getElementById( m )) &&
784							contains( context, elem ) &&
785							elem.id === m ) {
786
787							results.push( elem );
788							return results;
789						}
790					}
791
792				// Type selector
793				} else if ( match[2] ) {
794					push.apply( results, context.getElementsByTagName( selector ) );
795					return results;
796
797				// Class selector
798				} else if ( (m = match[3]) && support.getElementsByClassName &&
799					context.getElementsByClassName ) {
800
801					push.apply( results, context.getElementsByClassName( m ) );
802					return results;
803				}
804			}
805
806			// Take advantage of querySelectorAll
807			if ( support.qsa &&
808				!nonnativeSelectorCache[ selector + " " ] &&
809				(!rbuggyQSA || !rbuggyQSA.test( selector )) &&
810
811				// Support: IE 8 only
812				// Exclude object elements
813				(nodeType !== 1 || context.nodeName.toLowerCase() !== "object") ) {
814
815				newSelector = selector;
816				newContext = context;
817
818				// qSA considers elements outside a scoping root when evaluating child or
819				// descendant combinators, which is not what we want.
820				// In such cases, we work around the behavior by prefixing every selector in the
821				// list with an ID selector referencing the scope context.
822				// Thanks to Andrew Dupont for this technique.
823				if ( nodeType === 1 && rdescend.test( selector ) ) {
824
825					// Capture the context ID, setting it first if necessary
826					if ( (nid = context.getAttribute( "id" )) ) {
827						nid = nid.replace( rcssescape, fcssescape );
828					} else {
829						context.setAttribute( "id", (nid = expando) );
830					}
831
832					// Prefix every selector in the list
833					groups = tokenize( selector );
834					i = groups.length;
835					while ( i-- ) {
836						groups[i] = "#" + nid + " " + toSelector( groups[i] );
837					}
838					newSelector = groups.join( "," );
839
840					// Expand context for sibling selectors
841					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
842						context;
843				}
844
845				try {
846					push.apply( results,
847						newContext.querySelectorAll( newSelector )
848					);
849					return results;
850				} catch ( qsaError ) {
851					nonnativeSelectorCache( selector, true );
852				} finally {
853					if ( nid === expando ) {
854						context.removeAttribute( "id" );
855					}
856				}
857			}
858		}
859	}
860
861	// All others
862	return select( selector.replace( rtrim, "$1" ), context, results, seed );
863}
864
865/**
866 * Create key-value caches of limited size
867 * @returns {function(string, object)} Returns the Object data after storing it on itself with
868 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
869 *	deleting the oldest entry
870 */
871function createCache() {
872	var keys = [];
873
874	function cache( key, value ) {
875		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
876		if ( keys.push( key + " " ) > Expr.cacheLength ) {
877			// Only keep the most recent entries
878			delete cache[ keys.shift() ];
879		}
880		return (cache[ key + " " ] = value);
881	}
882	return cache;
883}
884
885/**
886 * Mark a function for special use by Sizzle
887 * @param {Function} fn The function to mark
888 */
889function markFunction( fn ) {
890	fn[ expando ] = true;
891	return fn;
892}
893
894/**
895 * Support testing using an element
896 * @param {Function} fn Passed the created element and returns a boolean result
897 */
898function assert( fn ) {
899	var el = document.createElement("fieldset");
900
901	try {
902		return !!fn( el );
903	} catch (e) {
904		return false;
905	} finally {
906		// Remove from its parent by default
907		if ( el.parentNode ) {
908			el.parentNode.removeChild( el );
909		}
910		// release memory in IE
911		el = null;
912	}
913}
914
915/**
916 * Adds the same handler for all of the specified attrs
917 * @param {String} attrs Pipe-separated list of attributes
918 * @param {Function} handler The method that will be applied
919 */
920function addHandle( attrs, handler ) {
921	var arr = attrs.split("|"),
922		i = arr.length;
923
924	while ( i-- ) {
925		Expr.attrHandle[ arr[i] ] = handler;
926	}
927}
928
929/**
930 * Checks document order of two siblings
931 * @param {Element} a
932 * @param {Element} b
933 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
934 */
935function siblingCheck( a, b ) {
936	var cur = b && a,
937		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
938			a.sourceIndex - b.sourceIndex;
939
940	// Use IE sourceIndex if available on both nodes
941	if ( diff ) {
942		return diff;
943	}
944
945	// Check if b follows a
946	if ( cur ) {
947		while ( (cur = cur.nextSibling) ) {
948			if ( cur === b ) {
949				return -1;
950			}
951		}
952	}
953
954	return a ? 1 : -1;
955}
956
957/**
958 * Returns a function to use in pseudos for input types
959 * @param {String} type
960 */
961function createInputPseudo( type ) {
962	return function( elem ) {
963		var name = elem.nodeName.toLowerCase();
964		return name === "input" && elem.type === type;
965	};
966}
967
968/**
969 * Returns a function to use in pseudos for buttons
970 * @param {String} type
971 */
972function createButtonPseudo( type ) {
973	return function( elem ) {
974		var name = elem.nodeName.toLowerCase();
975		return (name === "input" || name === "button") && elem.type === type;
976	};
977}
978
979/**
980 * Returns a function to use in pseudos for :enabled/:disabled
981 * @param {Boolean} disabled true for :disabled; false for :enabled
982 */
983function createDisabledPseudo( disabled ) {
984
985	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
986	return function( elem ) {
987
988		// Only certain elements can match :enabled or :disabled
989		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
990		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
991		if ( "form" in elem ) {
992
993			// Check for inherited disabledness on relevant non-disabled elements:
994			// * listed form-associated elements in a disabled fieldset
995			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
996			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
997			// * option elements in a disabled optgroup
998			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
999			// All such elements have a "form" property.
1000			if ( elem.parentNode && elem.disabled === false ) {
1001
1002				// Option elements defer to a parent optgroup if present
1003				if ( "label" in elem ) {
1004					if ( "label" in elem.parentNode ) {
1005						return elem.parentNode.disabled === disabled;
1006					} else {
1007						return elem.disabled === disabled;
1008					}
1009				}
1010
1011				// Support: IE 6 - 11
1012				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
1013				return elem.isDisabled === disabled ||
1014
1015					// Where there is no isDisabled, check manually
1016					/* jshint -W018 */
1017					elem.isDisabled !== !disabled &&
1018						inDisabledFieldset( elem ) === disabled;
1019			}
1020
1021			return elem.disabled === disabled;
1022
1023		// Try to winnow out elements that can't be disabled before trusting the disabled property.
1024		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
1025		// even exist on them, let alone have a boolean value.
1026		} else if ( "label" in elem ) {
1027			return elem.disabled === disabled;
1028		}
1029
1030		// Remaining elements are neither :enabled nor :disabled
1031		return false;
1032	};
1033}
1034
1035/**
1036 * Returns a function to use in pseudos for positionals
1037 * @param {Function} fn
1038 */
1039function createPositionalPseudo( fn ) {
1040	return markFunction(function( argument ) {
1041		argument = +argument;
1042		return markFunction(function( seed, matches ) {
1043			var j,
1044				matchIndexes = fn( [], seed.length, argument ),
1045				i = matchIndexes.length;
1046
1047			// Match elements found at the specified indexes
1048			while ( i-- ) {
1049				if ( seed[ (j = matchIndexes[i]) ] ) {
1050					seed[j] = !(matches[j] = seed[j]);
1051				}
1052			}
1053		});
1054	});
1055}
1056
1057/**
1058 * Checks a node for validity as a Sizzle context
vendor: 13,957 bytes, lines 1059-1520
1059 * @param {Element|Object=} context
1060 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1061 */
1062function testContext( context ) {
1063	return context && typeof context.getElementsByTagName !== "undefined" && context;
1064}
1065
1066// Expose support vars for convenience
1067support = Sizzle.support = {};
1068
1069/**
1070 * Detects XML nodes
1071 * @param {Element|Object} elem An element or a document
1072 * @returns {Boolean} True iff elem is a non-HTML XML node
1073 */
1074isXML = Sizzle.isXML = function( elem ) {
1075	var namespace = elem.namespaceURI,
1076		docElem = (elem.ownerDocument || elem).documentElement;
1077
1078	// Support: IE <=8
1079	// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
1080	// https://bugs.jquery.com/ticket/4833
1081	return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
1082};
1083
1084/**
1085 * Sets document-related variables once based on the current document
1086 * @param {Element|Object} [doc] An element or document object to use to set the document
1087 * @returns {Object} Returns the current document
1088 */
1089setDocument = Sizzle.setDocument = function( node ) {
1090	var hasCompare, subWindow,
1091		doc = node ? node.ownerDocument || node : preferredDoc;
1092
1093	// Return early if doc is invalid or already selected
1094	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1095		return document;
1096	}
1097
1098	// Update global variables
1099	document = doc;
1100	docElem = document.documentElement;
1101	documentIsHTML = !isXML( document );
1102
1103	// Support: IE 9-11, Edge
1104	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1105	if ( preferredDoc !== document &&
1106		(subWindow = document.defaultView) && subWindow.top !== subWindow ) {
1107
1108		// Support: IE 11, Edge
1109		if ( subWindow.addEventListener ) {
1110			subWindow.addEventListener( "unload", unloadHandler, false );
1111
1112		// Support: IE 9 - 10 only
1113		} else if ( subWindow.attachEvent ) {
1114			subWindow.attachEvent( "onunload", unloadHandler );
1115		}
1116	}
1117
1118	/* Attributes
1119	---------------------------------------------------------------------- */
1120
1121	// Support: IE<8
1122	// Verify that getAttribute really returns attributes and not properties
1123	// (excepting IE8 booleans)
1124	support.attributes = assert(function( el ) {
1125		el.className = "i";
1126		return !el.getAttribute("className");
1127	});
1128
1129	/* getElement(s)By*
1130	---------------------------------------------------------------------- */
1131
1132	// Check if getElementsByTagName("*") returns only elements
1133	support.getElementsByTagName = assert(function( el ) {
1134		el.appendChild( document.createComment("") );
1135		return !el.getElementsByTagName("*").length;
1136	});
1137
1138	// Support: IE<9
1139	support.getElementsByClassName = rnative.test( document.getElementsByClassName );
1140
1141	// Support: IE<10
1142	// Check if getElementById returns elements by name
1143	// The broken getElementById methods don't pick up programmatically-set names,
1144	// so use a roundabout getElementsByName test
1145	support.getById = assert(function( el ) {
1146		docElem.appendChild( el ).id = expando;
1147		return !document.getElementsByName || !document.getElementsByName( expando ).length;
1148	});
1149
1150	// ID filter and find
1151	if ( support.getById ) {
1152		Expr.filter["ID"] = function( id ) {
1153			var attrId = id.replace( runescape, funescape );
1154			return function( elem ) {
1155				return elem.getAttribute("id") === attrId;
1156			};
1157		};
1158		Expr.find["ID"] = function( id, context ) {
1159			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1160				var elem = context.getElementById( id );
1161				return elem ? [ elem ] : [];
1162			}
1163		};
1164	} else {
1165		Expr.filter["ID"] =  function( id ) {
1166			var attrId = id.replace( runescape, funescape );
1167			return function( elem ) {
1168				var node = typeof elem.getAttributeNode !== "undefined" &&
1169					elem.getAttributeNode("id");
1170				return node && node.value === attrId;
1171			};
1172		};
1173
1174		// Support: IE 6 - 7 only
1175		// getElementById is not reliable as a find shortcut
1176		Expr.find["ID"] = function( id, context ) {
1177			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1178				var node, i, elems,
1179					elem = context.getElementById( id );
1180
1181				if ( elem ) {
1182
1183					// Verify the id attribute
1184					node = elem.getAttributeNode("id");
1185					if ( node && node.value === id ) {
1186						return [ elem ];
1187					}
1188
1189					// Fall back on getElementsByName
1190					elems = context.getElementsByName( id );
1191					i = 0;
1192					while ( (elem = elems[i++]) ) {
1193						node = elem.getAttributeNode("id");
1194						if ( node && node.value === id ) {
1195							return [ elem ];
1196						}
1197					}
1198				}
1199
1200				return [];
1201			}
1202		};
1203	}
1204
1205	// Tag
1206	Expr.find["TAG"] = support.getElementsByTagName ?
1207		function( tag, context ) {
1208			if ( typeof context.getElementsByTagName !== "undefined" ) {
1209				return context.getElementsByTagName( tag );
1210
1211			// DocumentFragment nodes don't have gEBTN
1212			} else if ( support.qsa ) {
1213				return context.querySelectorAll( tag );
1214			}
1215		} :
1216
1217		function( tag, context ) {
1218			var elem,
1219				tmp = [],
1220				i = 0,
1221				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1222				results = context.getElementsByTagName( tag );
1223
1224			// Filter out possible comments
1225			if ( tag === "*" ) {
1226				while ( (elem = results[i++]) ) {
1227					if ( elem.nodeType === 1 ) {
1228						tmp.push( elem );
1229					}
1230				}
1231
1232				return tmp;
1233			}
1234			return results;
1235		};
1236
1237	// Class
1238	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1239		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1240			return context.getElementsByClassName( className );
1241		}
1242	};
1243
1244	/* QSA/matchesSelector
1245	---------------------------------------------------------------------- */
1246
1247	// QSA and matchesSelector support
1248
1249	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1250	rbuggyMatches = [];
1251
1252	// qSa(:focus) reports false when true (Chrome 21)
1253	// We allow this because of a bug in IE8/9 that throws an error
1254	// whenever `document.activeElement` is accessed on an iframe
1255	// So, we allow :focus to pass through QSA all the time to avoid the IE error
1256	// See https://bugs.jquery.com/ticket/13378
1257	rbuggyQSA = [];
1258
1259	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
1260		// Build QSA regex
1261		// Regex strategy adopted from Diego Perini
1262		assert(function( el ) {
1263			// Select is set to empty string on purpose
1264			// This is to test IE's treatment of not explicitly
1265			// setting a boolean content attribute,
1266			// since its presence should be enough
1267			// https://bugs.jquery.com/ticket/12359
1268			docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
1269				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
1270				"<option selected=''></option></select>";
1271
1272			// Support: IE8, Opera 11-12.16
1273			// Nothing should be selected when empty strings follow ^= or $= or *=
1274			// The test attribute must be unknown in Opera but "safe" for WinRT
1275			// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1276			if ( el.querySelectorAll("[msallowcapture^='']").length ) {
1277				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1278			}
1279
1280			// Support: IE8
1281			// Boolean attributes and "value" are not treated correctly
1282			if ( !el.querySelectorAll("[selected]").length ) {
1283				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1284			}
1285
1286			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
1287			if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1288				rbuggyQSA.push("~=");
1289			}
1290
1291			// Webkit/Opera - :checked should return selected option elements
1292			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1293			// IE8 throws error here and will not see later tests
1294			if ( !el.querySelectorAll(":checked").length ) {
1295				rbuggyQSA.push(":checked");
1296			}
1297
1298			// Support: Safari 8+, iOS 8+
1299			// https://bugs.webkit.org/show_bug.cgi?id=136851
1300			// In-page `selector#id sibling-combinator selector` fails
1301			if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1302				rbuggyQSA.push(".#.+[+~]");
1303			}
1304		});
1305
1306		assert(function( el ) {
1307			el.innerHTML = "<a href='' disabled='disabled'></a>" +
1308				"<select disabled='disabled'><option/></select>";
1309
1310			// Support: Windows 8 Native Apps
1311			// The type and name attributes are restricted during .innerHTML assignment
1312			var input = document.createElement("input");
1313			input.setAttribute( "type", "hidden" );
1314			el.appendChild( input ).setAttribute( "name", "D" );
1315
1316			// Support: IE8
1317			// Enforce case-sensitivity of name attribute
1318			if ( el.querySelectorAll("[name=d]").length ) {
1319				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1320			}
1321
1322			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1323			// IE8 throws error here and will not see later tests
1324			if ( el.querySelectorAll(":enabled").length !== 2 ) {
1325				rbuggyQSA.push( ":enabled", ":disabled" );
1326			}
1327
1328			// Support: IE9-11+
1329			// IE's :disabled selector does not pick up the children of disabled fieldsets
1330			docElem.appendChild( el ).disabled = true;
1331			if ( el.querySelectorAll(":disabled").length !== 2 ) {
1332				rbuggyQSA.push( ":enabled", ":disabled" );
1333			}
1334
1335			// Opera 10-11 does not throw on post-comma invalid pseudos
1336			el.querySelectorAll("*,:x");
1337			rbuggyQSA.push(",.*:");
1338		});
1339	}
1340
1341	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1342		docElem.webkitMatchesSelector ||
1343		docElem.mozMatchesSelector ||
1344		docElem.oMatchesSelector ||
1345		docElem.msMatchesSelector) )) ) {
1346
1347		assert(function( el ) {
1348			// Check to see if it's possible to do matchesSelector
1349			// on a disconnected node (IE 9)
1350			support.disconnectedMatch = matches.call( el, "*" );
1351
1352			// This should fail with an exception
1353			// Gecko does not error, returns false instead
1354			matches.call( el, "[s!='']:x" );
1355			rbuggyMatches.push( "!=", pseudos );
1356		});
1357	}
1358
1359	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1360	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1361
1362	/* Contains
1363	---------------------------------------------------------------------- */
1364	hasCompare = rnative.test( docElem.compareDocumentPosition );
1365
1366	// Element contains another
1367	// Purposefully self-exclusive
1368	// As in, an element does not contain itself
1369	contains = hasCompare || rnative.test( docElem.contains ) ?
1370		function( a, b ) {
1371			var adown = a.nodeType === 9 ? a.documentElement : a,
1372				bup = b && b.parentNode;
1373			return a === bup || !!( bup && bup.nodeType === 1 && (
1374				adown.contains ?
1375					adown.contains( bup ) :
1376					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1377			));
1378		} :
1379		function( a, b ) {
1380			if ( b ) {
1381				while ( (b = b.parentNode) ) {
1382					if ( b === a ) {
1383						return true;
1384					}
1385				}
1386			}
1387			return false;
1388		};
1389
1390	/* Sorting
1391	---------------------------------------------------------------------- */
1392
1393	// Document order sorting
1394	sortOrder = hasCompare ?
1395	function( a, b ) {
1396
1397		// Flag for duplicate removal
1398		if ( a === b ) {
1399			hasDuplicate = true;
1400			return 0;
1401		}
1402
1403		// Sort on method existence if only one input has compareDocumentPosition
1404		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1405		if ( compare ) {
1406			return compare;
1407		}
1408
1409		// Calculate position if both inputs belong to the same document
1410		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1411			a.compareDocumentPosition( b ) :
1412
1413			// Otherwise we know they are disconnected
1414			1;
1415
1416		// Disconnected nodes
1417		if ( compare & 1 ||
1418			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1419
1420			// Choose the first element that is related to our preferred document
1421			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1422				return -1;
1423			}
1424			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1425				return 1;
1426			}
1427
1428			// Maintain original order
1429			return sortInput ?
1430				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1431				0;
1432		}
1433
1434		return compare & 4 ? -1 : 1;
1435	} :
1436	function( a, b ) {
1437		// Exit early if the nodes are identical
1438		if ( a === b ) {
1439			hasDuplicate = true;
1440			return 0;
1441		}
1442
1443		var cur,
1444			i = 0,
1445			aup = a.parentNode,
1446			bup = b.parentNode,
1447			ap = [ a ],
1448			bp = [ b ];
1449
1450		// Parentless nodes are either documents or disconnected
1451		if ( !aup || !bup ) {
1452			return a === document ? -1 :
1453				b === document ? 1 :
1454				aup ? -1 :
1455				bup ? 1 :
1456				sortInput ?
1457				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1458				0;
1459
1460		// If the nodes are siblings, we can do a quick check
1461		} else if ( aup === bup ) {
1462			return siblingCheck( a, b );
1463		}
1464
1465		// Otherwise we need full lists of their ancestors for comparison
1466		cur = a;
1467		while ( (cur = cur.parentNode) ) {
1468			ap.unshift( cur );
1469		}
1470		cur = b;
1471		while ( (cur = cur.parentNode) ) {
1472			bp.unshift( cur );
1473		}
1474
1475		// Walk down the tree looking for a discrepancy
1476		while ( ap[i] === bp[i] ) {
1477			i++;
1478		}
1479
1480		return i ?
1481			// Do a sibling check if the nodes have a common ancestor
1482			siblingCheck( ap[i], bp[i] ) :
1483
1484			// Otherwise nodes in our document sort first
1485			ap[i] === preferredDoc ? -1 :
1486			bp[i] === preferredDoc ? 1 :
1487			0;
1488	};
1489
1490	return document;
1491};
1492
1493Sizzle.matches = function( expr, elements ) {
1494	return Sizzle( expr, null, null, elements );
1495};
1496
1497Sizzle.matchesSelector = function( elem, expr ) {
1498	// Set document vars if needed
1499	if ( ( elem.ownerDocument || elem ) !== document ) {
1500		setDocument( elem );
1501	}
1502
1503	if ( support.matchesSelector && documentIsHTML &&
1504		!nonnativeSelectorCache[ expr + " " ] &&
1505		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1506		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
1507
1508		try {
1509			var ret = matches.call( elem, expr );
1510
1511			// IE 9's matchesSelector returns false on disconnected nodes
1512			if ( ret || support.disconnectedMatch ||
1513					// As well, disconnected nodes are said to be in a document
1514					// fragment in IE 9
1515					elem.document && elem.document.nodeType !== 11 ) {
1516				return ret;
1517			}
1518		} catch (e) {
1519			nonnativeSelectorCache( expr, true );
1520		
vendor: 12,942 bytes, lines 1520-1979
1520}
1521	}
1522
1523	return Sizzle( expr, document, null, [ elem ] ).length > 0;
1524};
1525
1526Sizzle.contains = function( context, elem ) {
1527	// Set document vars if needed
1528	if ( ( context.ownerDocument || context ) !== document ) {
1529		setDocument( context );
1530	}
1531	return contains( context, elem );
1532};
1533
1534Sizzle.attr = function( elem, name ) {
1535	// Set document vars if needed
1536	if ( ( elem.ownerDocument || elem ) !== document ) {
1537		setDocument( elem );
1538	}
1539
1540	var fn = Expr.attrHandle[ name.toLowerCase() ],
1541		// Don't get fooled by Object.prototype properties (jQuery #13807)
1542		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1543			fn( elem, name, !documentIsHTML ) :
1544			undefined;
1545
1546	return val !== undefined ?
1547		val :
1548		support.attributes || !documentIsHTML ?
1549			elem.getAttribute( name ) :
1550			(val = elem.getAttributeNode(name)) && val.specified ?
1551				val.value :
1552				null;
1553};
1554
1555Sizzle.escape = function( sel ) {
1556	return (sel + "").replace( rcssescape, fcssescape );
1557};
1558
1559Sizzle.error = function( msg ) {
1560	throw new Error( "Syntax error, unrecognized expression: " + msg );
1561};
1562
1563/**
1564 * Document sorting and removing duplicates
1565 * @param {ArrayLike} results
1566 */
1567Sizzle.uniqueSort = function( results ) {
1568	var elem,
1569		duplicates = [],
1570		j = 0,
1571		i = 0;
1572
1573	// Unless we *know* we can detect duplicates, assume their presence
1574	hasDuplicate = !support.detectDuplicates;
1575	sortInput = !support.sortStable && results.slice( 0 );
1576	results.sort( sortOrder );
1577
1578	if ( hasDuplicate ) {
1579		while ( (elem = results[i++]) ) {
1580			if ( elem === results[ i ] ) {
1581				j = duplicates.push( i );
1582			}
1583		}
1584		while ( j-- ) {
1585			results.splice( duplicates[ j ], 1 );
1586		}
1587	}
1588
1589	// Clear input after sorting to release objects
1590	// See https://github.com/jquery/sizzle/pull/225
1591	sortInput = null;
1592
1593	return results;
1594};
1595
1596/**
1597 * Utility function for retrieving the text value of an array of DOM nodes
1598 * @param {Array|Element} elem
1599 */
1600getText = Sizzle.getText = function( elem ) {
1601	var node,
1602		ret = "",
1603		i = 0,
1604		nodeType = elem.nodeType;
1605
1606	if ( !nodeType ) {
1607		// If no nodeType, this is expected to be an array
1608		while ( (node = elem[i++]) ) {
1609			// Do not traverse comment nodes
1610			ret += getText( node );
1611		}
1612	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1613		// Use textContent for elements
1614		// innerText usage removed for consistency of new lines (jQuery #11153)
1615		if ( typeof elem.textContent === "string" ) {
1616			return elem.textContent;
1617		} else {
1618			// Traverse its children
1619			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1620				ret += getText( elem );
1621			}
1622		}
1623	} else if ( nodeType === 3 || nodeType === 4 ) {
1624		return elem.nodeValue;
1625	}
1626	// Do not include comment or processing instruction nodes
1627
1628	return ret;
1629};
1630
1631Expr = Sizzle.selectors = {
1632
1633	// Can be adjusted by the user
1634	cacheLength: 50,
1635
1636	createPseudo: markFunction,
1637
1638	match: matchExpr,
1639
1640	attrHandle: {},
1641
1642	find: {},
1643
1644	relative: {
1645		">": { dir: "parentNode", first: true },
1646		" ": { dir: "parentNode" },
1647		"+": { dir: "previousSibling", first: true },
1648		"~": { dir: "previousSibling" }
1649	},
1650
1651	preFilter: {
1652		"ATTR": function( match ) {
1653			match[1] = match[1].replace( runescape, funescape );
1654
1655			// Move the given value to match[3] whether quoted or unquoted
1656			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1657
1658			if ( match[2] === "~=" ) {
1659				match[3] = " " + match[3] + " ";
1660			}
1661
1662			return match.slice( 0, 4 );
1663		},
1664
1665		"CHILD": function( match ) {
1666			/* matches from matchExpr["CHILD"]
1667				1 type (only|nth|...)
1668				2 what (child|of-type)
1669				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1670				4 xn-component of xn+y argument ([+-]?\d*n|)
1671				5 sign of xn-component
1672				6 x of xn-component
1673				7 sign of y-component
1674				8 y of y-component
1675			*/
1676			match[1] = match[1].toLowerCase();
1677
1678			if ( match[1].slice( 0, 3 ) === "nth" ) {
1679				// nth-* requires argument
1680				if ( !match[3] ) {
1681					Sizzle.error( match[0] );
1682				}
1683
1684				// numeric x and y parameters for Expr.filter.CHILD
1685				// remember that false/true cast respectively to 0/1
1686				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1687				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1688
1689			// other types prohibit arguments
1690			} else if ( match[3] ) {
1691				Sizzle.error( match[0] );
1692			}
1693
1694			return match;
1695		},
1696
1697		"PSEUDO": function( match ) {
1698			var excess,
1699				unquoted = !match[6] && match[2];
1700
1701			if ( matchExpr["CHILD"].test( match[0] ) ) {
1702				return null;
1703			}
1704
1705			// Accept quoted arguments as-is
1706			if ( match[3] ) {
1707				match[2] = match[4] || match[5] || "";
1708
1709			// Strip excess characters from unquoted arguments
1710			} else if ( unquoted && rpseudo.test( unquoted ) &&
1711				// Get excess from tokenize (recursively)
1712				(excess = tokenize( unquoted, true )) &&
1713				// advance to the next closing parenthesis
1714				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1715
1716				// excess is a negative index
1717				match[0] = match[0].slice( 0, excess );
1718				match[2] = unquoted.slice( 0, excess );
1719			}
1720
1721			// Return only captures needed by the pseudo filter method (type and argument)
1722			return match.slice( 0, 3 );
1723		}
1724	},
1725
1726	filter: {
1727
1728		"TAG": function( nodeNameSelector ) {
1729			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1730			return nodeNameSelector === "*" ?
1731				function() { return true; } :
1732				function( elem ) {
1733					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1734				};
1735		},
1736
1737		"CLASS": function( className ) {
1738			var pattern = classCache[ className + " " ];
1739
1740			return pattern ||
1741				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1742				classCache( className, function( elem ) {
1743					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1744				});
1745		},
1746
1747		"ATTR": function( name, operator, check ) {
1748			return function( elem ) {
1749				var result = Sizzle.attr( elem, name );
1750
1751				if ( result == null ) {
1752					return operator === "!=";
1753				}
1754				if ( !operator ) {
1755					return true;
1756				}
1757
1758				result += "";
1759
1760				return operator === "=" ? result === check :
1761					operator === "!=" ? result !== check :
1762					operator === "^=" ? check && result.indexOf( check ) === 0 :
1763					operator === "*=" ? check && result.indexOf( check ) > -1 :
1764					operator === "$=" ? check && result.slice( -check.length ) === check :
1765					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1766					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1767					false;
1768			};
1769		},
1770
1771		"CHILD": function( type, what, argument, first, last ) {
1772			var simple = type.slice( 0, 3 ) !== "nth",
1773				forward = type.slice( -4 ) !== "last",
1774				ofType = what === "of-type";
1775
1776			return first === 1 && last === 0 ?
1777
1778				// Shortcut for :nth-*(n)
1779				function( elem ) {
1780					return !!elem.parentNode;
1781				} :
1782
1783				function( elem, context, xml ) {
1784					var cache, uniqueCache, outerCache, node, nodeIndex, start,
1785						dir = simple !== forward ? "nextSibling" : "previousSibling",
1786						parent = elem.parentNode,
1787						name = ofType && elem.nodeName.toLowerCase(),
1788						useCache = !xml && !ofType,
1789						diff = false;
1790
1791					if ( parent ) {
1792
1793						// :(first|last|only)-(child|of-type)
1794						if ( simple ) {
1795							while ( dir ) {
1796								node = elem;
1797								while ( (node = node[ dir ]) ) {
1798									if ( ofType ?
1799										node.nodeName.toLowerCase() === name :
1800										node.nodeType === 1 ) {
1801
1802										return false;
1803									}
1804								}
1805								// Reverse direction for :only-* (if we haven't yet done so)
1806								start = dir = type === "only" && !start && "nextSibling";
1807							}
1808							return true;
1809						}
1810
1811						start = [ forward ? parent.firstChild : parent.lastChild ];
1812
1813						// non-xml :nth-child(...) stores cache data on `parent`
1814						if ( forward && useCache ) {
1815
1816							// Seek `elem` from a previously-cached index
1817
1818							// ...in a gzip-friendly way
1819							node = parent;
1820							outerCache = node[ expando ] || (node[ expando ] = {});
1821
1822							// Support: IE <9 only
1823							// Defend against cloned attroperties (jQuery gh-1709)
1824							uniqueCache = outerCache[ node.uniqueID ] ||
1825								(outerCache[ node.uniqueID ] = {});
1826
1827							cache = uniqueCache[ type ] || [];
1828							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1829							diff = nodeIndex && cache[ 2 ];
1830							node = nodeIndex && parent.childNodes[ nodeIndex ];
1831
1832							while ( (node = ++nodeIndex && node && node[ dir ] ||
1833
1834								// Fallback to seeking `elem` from the start
1835								(diff = nodeIndex = 0) || start.pop()) ) {
1836
1837								// When found, cache indexes on `parent` and break
1838								if ( node.nodeType === 1 && ++diff && node === elem ) {
1839									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
1840									break;
1841								}
1842							}
1843
1844						} else {
1845							// Use previously-cached element index if available
1846							if ( useCache ) {
1847								// ...in a gzip-friendly way
1848								node = elem;
1849								outerCache = node[ expando ] || (node[ expando ] = {});
1850
1851								// Support: IE <9 only
1852								// Defend against cloned attroperties (jQuery gh-1709)
1853								uniqueCache = outerCache[ node.uniqueID ] ||
1854									(outerCache[ node.uniqueID ] = {});
1855
1856								cache = uniqueCache[ type ] || [];
1857								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1858								diff = nodeIndex;
1859							}
1860
1861							// xml :nth-child(...)
1862							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
1863							if ( diff === false ) {
1864								// Use the same loop as above to seek `elem` from the start
1865								while ( (node = ++nodeIndex && node && node[ dir ] ||
1866									(diff = nodeIndex = 0) || start.pop()) ) {
1867
1868									if ( ( ofType ?
1869										node.nodeName.toLowerCase() === name :
1870										node.nodeType === 1 ) &&
1871										++diff ) {
1872
1873										// Cache the index of each encountered element
1874										if ( useCache ) {
1875											outerCache = node[ expando ] || (node[ expando ] = {});
1876
1877											// Support: IE <9 only
1878											// Defend against cloned attroperties (jQuery gh-1709)
1879											uniqueCache = outerCache[ node.uniqueID ] ||
1880												(outerCache[ node.uniqueID ] = {});
1881
1882											uniqueCache[ type ] = [ dirruns, diff ];
1883										}
1884
1885										if ( node === elem ) {
1886											break;
1887										}
1888									}
1889								}
1890							}
1891						}
1892
1893						// Incorporate the offset, then check against cycle size
1894						diff -= last;
1895						return diff === first || ( diff % first === 0 && diff / first >= 0 );
1896					}
1897				};
1898		},
1899
1900		"PSEUDO": function( pseudo, argument ) {
1901			// pseudo-class names are case-insensitive
1902			// http://www.w3.org/TR/selectors/#pseudo-classes
1903			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1904			// Remember that setFilters inherits from pseudos
1905			var args,
1906				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1907					Sizzle.error( "unsupported pseudo: " + pseudo );
1908
1909			// The user may use createPseudo to indicate that
1910			// arguments are needed to create the filter function
1911			// just as Sizzle does
1912			if ( fn[ expando ] ) {
1913				return fn( argument );
1914			}
1915
1916			// But maintain support for old signatures
1917			if ( fn.length > 1 ) {
1918				args = [ pseudo, pseudo, "", argument ];
1919				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1920					markFunction(function( seed, matches ) {
1921						var idx,
1922							matched = fn( seed, argument ),
1923							i = matched.length;
1924						while ( i-- ) {
1925							idx = indexOf( seed, matched[i] );
1926							seed[ idx ] = !( matches[ idx ] = matched[i] );
1927						}
1928					}) :
1929					function( elem ) {
1930						return fn( elem, 0, args );
1931					};
1932			}
1933
1934			return fn;
1935		}
1936	},
1937
1938	pseudos: {
1939		// Potentially complex pseudos
1940		"not": markFunction(function( selector ) {
1941			// Trim the selector passed to compile
1942			// to avoid treating leading and trailing
1943			// spaces as combinators
1944			var input = [],
1945				results = [],
1946				matcher = compile( selector.replace( rtrim, "$1" ) );
1947
1948			return matcher[ expando ] ?
1949				markFunction(function( seed, matches, context, xml ) {
1950					var elem,
1951						unmatched = matcher( seed, null, xml, [] ),
1952						i = seed.length;
1953
1954					// Match elements unmatched by `matcher`
1955					while ( i-- ) {
1956						if ( (elem = unmatched[i]) ) {
1957							seed[i] = !(matches[i] = elem);
1958						}
1959					}
1960				}) :
1961				function( elem, context, xml ) {
1962					input[0] = elem;
1963					matcher( input, null, xml, results );
1964					// Don't keep the element (issue #299)
1965					input[0] = null;
1966					return !results.pop();
1967				};
1968		}),
1969
1970		"has": markFunction(function( selector ) {
1971			return function( elem ) {
1972				return Sizzle( selector, elem ).length > 0;
1973			};
1974		}),
1975
1976		"contains": markFunction(function( text ) {
1977			text = text.replace( runescape, funescape );
1978			return function( elem ) {
1979				return ( elem.textContent || 
vendor: 25,129 bytes, lines 1979-2883
1979getText( elem ) ).indexOf( text ) > -1;
1980			};
1981		}),
1982
1983		// "Whether an element is represented by a :lang() selector
1984		// is based solely on the element's language value
1985		// being equal to the identifier C,
1986		// or beginning with the identifier C immediately followed by "-".
1987		// The matching of C against the element's language value is performed case-insensitively.
1988		// The identifier C does not have to be a valid language name."
1989		// http://www.w3.org/TR/selectors/#lang-pseudo
1990		"lang": markFunction( function( lang ) {
1991			// lang value must be a valid identifier
1992			if ( !ridentifier.test(lang || "") ) {
1993				Sizzle.error( "unsupported lang: " + lang );
1994			}
1995			lang = lang.replace( runescape, funescape ).toLowerCase();
1996			return function( elem ) {
1997				var elemLang;
1998				do {
1999					if ( (elemLang = documentIsHTML ?
2000						elem.lang :
2001						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
2002
2003						elemLang = elemLang.toLowerCase();
2004						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
2005					}
2006				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
2007				return false;
2008			};
2009		}),
2010
2011		// Miscellaneous
2012		"target": function( elem ) {
2013			var hash = window.location && window.location.hash;
2014			return hash && hash.slice( 1 ) === elem.id;
2015		},
2016
2017		"root": function( elem ) {
2018			return elem === docElem;
2019		},
2020
2021		"focus": function( elem ) {
2022			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2023		},
2024
2025		// Boolean properties
2026		"enabled": createDisabledPseudo( false ),
2027		"disabled": createDisabledPseudo( true ),
2028
2029		"checked": function( elem ) {
2030			// In CSS3, :checked should return both checked and selected elements
2031			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2032			var nodeName = elem.nodeName.toLowerCase();
2033			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2034		},
2035
2036		"selected": function( elem ) {
2037			// Accessing this property makes selected-by-default
2038			// options in Safari work properly
2039			if ( elem.parentNode ) {
2040				elem.parentNode.selectedIndex;
2041			}
2042
2043			return elem.selected === true;
2044		},
2045
2046		// Contents
2047		"empty": function( elem ) {
2048			// http://www.w3.org/TR/selectors/#empty-pseudo
2049			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2050			//   but not by others (comment: 8; processing instruction: 7; etc.)
2051			// nodeType < 6 works because attributes (2) do not appear as children
2052			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2053				if ( elem.nodeType < 6 ) {
2054					return false;
2055				}
2056			}
2057			return true;
2058		},
2059
2060		"parent": function( elem ) {
2061			return !Expr.pseudos["empty"]( elem );
2062		},
2063
2064		// Element/input types
2065		"header": function( elem ) {
2066			return rheader.test( elem.nodeName );
2067		},
2068
2069		"input": function( elem ) {
2070			return rinputs.test( elem.nodeName );
2071		},
2072
2073		"button": function( elem ) {
2074			var name = elem.nodeName.toLowerCase();
2075			return name === "input" && elem.type === "button" || name === "button";
2076		},
2077
2078		"text": function( elem ) {
2079			var attr;
2080			return elem.nodeName.toLowerCase() === "input" &&
2081				elem.type === "text" &&
2082
2083				// Support: IE<8
2084				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2085				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2086		},
2087
2088		// Position-in-collection
2089		"first": createPositionalPseudo(function() {
2090			return [ 0 ];
2091		}),
2092
2093		"last": createPositionalPseudo(function( matchIndexes, length ) {
2094			return [ length - 1 ];
2095		}),
2096
2097		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2098			return [ argument < 0 ? argument + length : argument ];
2099		}),
2100
2101		"even": createPositionalPseudo(function( matchIndexes, length ) {
2102			var i = 0;
2103			for ( ; i < length; i += 2 ) {
2104				matchIndexes.push( i );
2105			}
2106			return matchIndexes;
2107		}),
2108
2109		"odd": createPositionalPseudo(function( matchIndexes, length ) {
2110			var i = 1;
2111			for ( ; i < length; i += 2 ) {
2112				matchIndexes.push( i );
2113			}
2114			return matchIndexes;
2115		}),
2116
2117		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2118			var i = argument < 0 ?
2119				argument + length :
2120				argument > length ?
2121					length :
2122					argument;
2123			for ( ; --i >= 0; ) {
2124				matchIndexes.push( i );
2125			}
2126			return matchIndexes;
2127		}),
2128
2129		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2130			var i = argument < 0 ? argument + length : argument;
2131			for ( ; ++i < length; ) {
2132				matchIndexes.push( i );
2133			}
2134			return matchIndexes;
2135		})
2136	}
2137};
2138
2139Expr.pseudos["nth"] = Expr.pseudos["eq"];
2140
2141// Add button/input type pseudos
2142for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2143	Expr.pseudos[ i ] = createInputPseudo( i );
2144}
2145for ( i in { submit: true, reset: true } ) {
2146	Expr.pseudos[ i ] = createButtonPseudo( i );
2147}
2148
2149// Easy API for creating new setFilters
2150function setFilters() {}
2151setFilters.prototype = Expr.filters = Expr.pseudos;
2152Expr.setFilters = new setFilters();
2153
2154tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2155	var matched, match, tokens, type,
2156		soFar, groups, preFilters,
2157		cached = tokenCache[ selector + " " ];
2158
2159	if ( cached ) {
2160		return parseOnly ? 0 : cached.slice( 0 );
2161	}
2162
2163	soFar = selector;
2164	groups = [];
2165	preFilters = Expr.preFilter;
2166
2167	while ( soFar ) {
2168
2169		// Comma and first run
2170		if ( !matched || (match = rcomma.exec( soFar )) ) {
2171			if ( match ) {
2172				// Don't consume trailing commas as valid
2173				soFar = soFar.slice( match[0].length ) || soFar;
2174			}
2175			groups.push( (tokens = []) );
2176		}
2177
2178		matched = false;
2179
2180		// Combinators
2181		if ( (match = rcombinators.exec( soFar )) ) {
2182			matched = match.shift();
2183			tokens.push({
2184				value: matched,
2185				// Cast descendant combinators to space
2186				type: match[0].replace( rtrim, " " )
2187			});
2188			soFar = soFar.slice( matched.length );
2189		}
2190
2191		// Filters
2192		for ( type in Expr.filter ) {
2193			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2194				(match = preFilters[ type ]( match ))) ) {
2195				matched = match.shift();
2196				tokens.push({
2197					value: matched,
2198					type: type,
2199					matches: match
2200				});
2201				soFar = soFar.slice( matched.length );
2202			}
2203		}
2204
2205		if ( !matched ) {
2206			break;
2207		}
2208	}
2209
2210	// Return the length of the invalid excess
2211	// if we're just parsing
2212	// Otherwise, throw an error or return tokens
2213	return parseOnly ?
2214		soFar.length :
2215		soFar ?
2216			Sizzle.error( selector ) :
2217			// Cache the tokens
2218			tokenCache( selector, groups ).slice( 0 );
2219};
2220
2221function toSelector( tokens ) {
2222	var i = 0,
2223		len = tokens.length,
2224		selector = "";
2225	for ( ; i < len; i++ ) {
2226		selector += tokens[i].value;
2227	}
2228	return selector;
2229}
2230
2231function addCombinator( matcher, combinator, base ) {
2232	var dir = combinator.dir,
2233		skip = combinator.next,
2234		key = skip || dir,
2235		checkNonElements = base && key === "parentNode",
2236		doneName = done++;
2237
2238	return combinator.first ?
2239		// Check against closest ancestor/preceding element
2240		function( elem, context, xml ) {
2241			while ( (elem = elem[ dir ]) ) {
2242				if ( elem.nodeType === 1 || checkNonElements ) {
2243					return matcher( elem, context, xml );
2244				}
2245			}
2246			return false;
2247		} :
2248
2249		// Check against all ancestor/preceding elements
2250		function( elem, context, xml ) {
2251			var oldCache, uniqueCache, outerCache,
2252				newCache = [ dirruns, doneName ];
2253
2254			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2255			if ( xml ) {
2256				while ( (elem = elem[ dir ]) ) {
2257					if ( elem.nodeType === 1 || checkNonElements ) {
2258						if ( matcher( elem, context, xml ) ) {
2259							return true;
2260						}
2261					}
2262				}
2263			} else {
2264				while ( (elem = elem[ dir ]) ) {
2265					if ( elem.nodeType === 1 || checkNonElements ) {
2266						outerCache = elem[ expando ] || (elem[ expando ] = {});
2267
2268						// Support: IE <9 only
2269						// Defend against cloned attroperties (jQuery gh-1709)
2270						uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
2271
2272						if ( skip && skip === elem.nodeName.toLowerCase() ) {
2273							elem = elem[ dir ] || elem;
2274						} else if ( (oldCache = uniqueCache[ key ]) &&
2275							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2276
2277							// Assign to newCache so results back-propagate to previous elements
2278							return (newCache[ 2 ] = oldCache[ 2 ]);
2279						} else {
2280							// Reuse newcache so results back-propagate to previous elements
2281							uniqueCache[ key ] = newCache;
2282
2283							// A match means we're done; a fail means we have to keep checking
2284							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2285								return true;
2286							}
2287						}
2288					}
2289				}
2290			}
2291			return false;
2292		};
2293}
2294
2295function elementMatcher( matchers ) {
2296	return matchers.length > 1 ?
2297		function( elem, context, xml ) {
2298			var i = matchers.length;
2299			while ( i-- ) {
2300				if ( !matchers[i]( elem, context, xml ) ) {
2301					return false;
2302				}
2303			}
2304			return true;
2305		} :
2306		matchers[0];
2307}
2308
2309function multipleContexts( selector, contexts, results ) {
2310	var i = 0,
2311		len = contexts.length;
2312	for ( ; i < len; i++ ) {
2313		Sizzle( selector, contexts[i], results );
2314	}
2315	return results;
2316}
2317
2318function condense( unmatched, map, filter, context, xml ) {
2319	var elem,
2320		newUnmatched = [],
2321		i = 0,
2322		len = unmatched.length,
2323		mapped = map != null;
2324
2325	for ( ; i < len; i++ ) {
2326		if ( (elem = unmatched[i]) ) {
2327			if ( !filter || filter( elem, context, xml ) ) {
2328				newUnmatched.push( elem );
2329				if ( mapped ) {
2330					map.push( i );
2331				}
2332			}
2333		}
2334	}
2335
2336	return newUnmatched;
2337}
2338
2339function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2340	if ( postFilter && !postFilter[ expando ] ) {
2341		postFilter = setMatcher( postFilter );
2342	}
2343	if ( postFinder && !postFinder[ expando ] ) {
2344		postFinder = setMatcher( postFinder, postSelector );
2345	}
2346	return markFunction(function( seed, results, context, xml ) {
2347		var temp, i, elem,
2348			preMap = [],
2349			postMap = [],
2350			preexisting = results.length,
2351
2352			// Get initial elements from seed or context
2353			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2354
2355			// Prefilter to get matcher input, preserving a map for seed-results synchronization
2356			matcherIn = preFilter && ( seed || !selector ) ?
2357				condense( elems, preMap, preFilter, context, xml ) :
2358				elems,
2359
2360			matcherOut = matcher ?
2361				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2362				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2363
2364					// ...intermediate processing is necessary
2365					[] :
2366
2367					// ...otherwise use results directly
2368					results :
2369				matcherIn;
2370
2371		// Find primary matches
2372		if ( matcher ) {
2373			matcher( matcherIn, matcherOut, context, xml );
2374		}
2375
2376		// Apply postFilter
2377		if ( postFilter ) {
2378			temp = condense( matcherOut, postMap );
2379			postFilter( temp, [], context, xml );
2380
2381			// Un-match failing elements by moving them back to matcherIn
2382			i = temp.length;
2383			while ( i-- ) {
2384				if ( (elem = temp[i]) ) {
2385					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2386				}
2387			}
2388		}
2389
2390		if ( seed ) {
2391			if ( postFinder || preFilter ) {
2392				if ( postFinder ) {
2393					// Get the final matcherOut by condensing this intermediate into postFinder contexts
2394					temp = [];
2395					i = matcherOut.length;
2396					while ( i-- ) {
2397						if ( (elem = matcherOut[i]) ) {
2398							// Restore matcherIn since elem is not yet a final match
2399							temp.push( (matcherIn[i] = elem) );
2400						}
2401					}
2402					postFinder( null, (matcherOut = []), temp, xml );
2403				}
2404
2405				// Move matched elements from seed to results to keep them synchronized
2406				i = matcherOut.length;
2407				while ( i-- ) {
2408					if ( (elem = matcherOut[i]) &&
2409						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2410
2411						seed[temp] = !(results[temp] = elem);
2412					}
2413				}
2414			}
2415
2416		// Add elements to results, through postFinder if defined
2417		} else {
2418			matcherOut = condense(
2419				matcherOut === results ?
2420					matcherOut.splice( preexisting, matcherOut.length ) :
2421					matcherOut
2422			);
2423			if ( postFinder ) {
2424				postFinder( null, results, matcherOut, xml );
2425			} else {
2426				push.apply( results, matcherOut );
2427			}
2428		}
2429	});
2430}
2431
2432function matcherFromTokens( tokens ) {
2433	var checkContext, matcher, j,
2434		len = tokens.length,
2435		leadingRelative = Expr.relative[ tokens[0].type ],
2436		implicitRelative = leadingRelative || Expr.relative[" "],
2437		i = leadingRelative ? 1 : 0,
2438
2439		// The foundational matcher ensures that elements are reachable from top-level context(s)
2440		matchContext = addCombinator( function( elem ) {
2441			return elem === checkContext;
2442		}, implicitRelative, true ),
2443		matchAnyContext = addCombinator( function( elem ) {
2444			return indexOf( checkContext, elem ) > -1;
2445		}, implicitRelative, true ),
2446		matchers = [ function( elem, context, xml ) {
2447			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2448				(checkContext = context).nodeType ?
2449					matchContext( elem, context, xml ) :
2450					matchAnyContext( elem, context, xml ) );
2451			// Avoid hanging onto element (issue #299)
2452			checkContext = null;
2453			return ret;
2454		} ];
2455
2456	for ( ; i < len; i++ ) {
2457		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2458			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2459		} else {
2460			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2461
2462			// Return special upon seeing a positional matcher
2463			if ( matcher[ expando ] ) {
2464				// Find the next relative operator (if any) for proper handling
2465				j = ++i;
2466				for ( ; j < len; j++ ) {
2467					if ( Expr.relative[ tokens[j].type ] ) {
2468						break;
2469					}
2470				}
2471				return setMatcher(
2472					i > 1 && elementMatcher( matchers ),
2473					i > 1 && toSelector(
2474						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2475						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2476					).replace( rtrim, "$1" ),
2477					matcher,
2478					i < j && matcherFromTokens( tokens.slice( i, j ) ),
2479					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2480					j < len && toSelector( tokens )
2481				);
2482			}
2483			matchers.push( matcher );
2484		}
2485	}
2486
2487	return elementMatcher( matchers );
2488}
2489
2490function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2491	var bySet = setMatchers.length > 0,
2492		byElement = elementMatchers.length > 0,
2493		superMatcher = function( seed, context, xml, results, outermost ) {
2494			var elem, j, matcher,
2495				matchedCount = 0,
2496				i = "0",
2497				unmatched = seed && [],
2498				setMatched = [],
2499				contextBackup = outermostContext,
2500				// We must always have either seed elements or outermost context
2501				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2502				// Use integer dirruns iff this is the outermost matcher
2503				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2504				len = elems.length;
2505
2506			if ( outermost ) {
2507				outermostContext = context === document || context || outermost;
2508			}
2509
2510			// Add elements passing elementMatchers directly to results
2511			// Support: IE<9, Safari
2512			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2513			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2514				if ( byElement && elem ) {
2515					j = 0;
2516					if ( !context && elem.ownerDocument !== document ) {
2517						setDocument( elem );
2518						xml = !documentIsHTML;
2519					}
2520					while ( (matcher = elementMatchers[j++]) ) {
2521						if ( matcher( elem, context || document, xml) ) {
2522							results.push( elem );
2523							break;
2524						}
2525					}
2526					if ( outermost ) {
2527						dirruns = dirrunsUnique;
2528					}
2529				}
2530
2531				// Track unmatched elements for set filters
2532				if ( bySet ) {
2533					// They will have gone through all possible matchers
2534					if ( (elem = !matcher && elem) ) {
2535						matchedCount--;
2536					}
2537
2538					// Lengthen the array for every element, matched or not
2539					if ( seed ) {
2540						unmatched.push( elem );
2541					}
2542				}
2543			}
2544
2545			// `i` is now the count of elements visited above, and adding it to `matchedCount`
2546			// makes the latter nonnegative.
2547			matchedCount += i;
2548
2549			// Apply set filters to unmatched elements
2550			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2551			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2552			// no element matchers and no seed.
2553			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2554			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
2555			// numerically zero.
2556			if ( bySet && i !== matchedCount ) {
2557				j = 0;
2558				while ( (matcher = setMatchers[j++]) ) {
2559					matcher( unmatched, setMatched, context, xml );
2560				}
2561
2562				if ( seed ) {
2563					// Reintegrate element matches to eliminate the need for sorting
2564					if ( matchedCount > 0 ) {
2565						while ( i-- ) {
2566							if ( !(unmatched[i] || setMatched[i]) ) {
2567								setMatched[i] = pop.call( results );
2568							}
2569						}
2570					}
2571
2572					// Discard index placeholder values to get only actual matches
2573					setMatched = condense( setMatched );
2574				}
2575
2576				// Add matches to results
2577				push.apply( results, setMatched );
2578
2579				// Seedless set matches succeeding multiple successful matchers stipulate sorting
2580				if ( outermost && !seed && setMatched.length > 0 &&
2581					( matchedCount + setMatchers.length ) > 1 ) {
2582
2583					Sizzle.uniqueSort( results );
2584				}
2585			}
2586
2587			// Override manipulation of globals by nested matchers
2588			if ( outermost ) {
2589				dirruns = dirrunsUnique;
2590				outermostContext = contextBackup;
2591			}
2592
2593			return unmatched;
2594		};
2595
2596	return bySet ?
2597		markFunction( superMatcher ) :
2598		superMatcher;
2599}
2600
2601compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2602	var i,
2603		setMatchers = [],
2604		elementMatchers = [],
2605		cached = compilerCache[ selector + " " ];
2606
2607	if ( !cached ) {
2608		// Generate a function of recursive functions that can be used to check each element
2609		if ( !match ) {
2610			match = tokenize( selector );
2611		}
2612		i = match.length;
2613		while ( i-- ) {
2614			cached = matcherFromTokens( match[i] );
2615			if ( cached[ expando ] ) {
2616				setMatchers.push( cached );
2617			} else {
2618				elementMatchers.push( cached );
2619			}
2620		}
2621
2622		// Cache the compiled function
2623		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2624
2625		// Save selector and tokenization
2626		cached.selector = selector;
2627	}
2628	return cached;
2629};
2630
2631/**
2632 * A low-level selection function that works with Sizzle's compiled
2633 *  selector functions
2634 * @param {String|Function} selector A selector or a pre-compiled
2635 *  selector function built with Sizzle.compile
2636 * @param {Element} context
2637 * @param {Array} [results]
2638 * @param {Array} [seed] A set of elements to match against
2639 */
2640select = Sizzle.select = function( selector, context, results, seed ) {
2641	var i, tokens, token, type, find,
2642		compiled = typeof selector === "function" && selector,
2643		match = !seed && tokenize( (selector = compiled.selector || selector) );
2644
2645	results = results || [];
2646
2647	// Try to minimize operations if there is only one selector in the list and no seed
2648	// (the latter of which guarantees us context)
2649	if ( match.length === 1 ) {
2650
2651		// Reduce context if the leading compound selector is an ID
2652		tokens = match[0] = match[0].slice( 0 );
2653		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2654				context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
2655
2656			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2657			if ( !context ) {
2658				return results;
2659
2660			// Precompiled matchers will still verify ancestry, so step up a level
2661			} else if ( compiled ) {
2662				context = context.parentNode;
2663			}
2664
2665			selector = selector.slice( tokens.shift().value.length );
2666		}
2667
2668		// Fetch a seed set for right-to-left matching
2669		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2670		while ( i-- ) {
2671			token = tokens[i];
2672
2673			// Abort if we hit a combinator
2674			if ( Expr.relative[ (type = token.type) ] ) {
2675				break;
2676			}
2677			if ( (find = Expr.find[ type ]) ) {
2678				// Search, expanding context for leading sibling combinators
2679				if ( (seed = find(
2680					token.matches[0].replace( runescape, funescape ),
2681					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2682				)) ) {
2683
2684					// If seed is empty or no tokens remain, we can return early
2685					tokens.splice( i, 1 );
2686					selector = seed.length && toSelector( tokens );
2687					if ( !selector ) {
2688						push.apply( results, seed );
2689						return results;
2690					}
2691
2692					break;
2693				}
2694			}
2695		}
2696	}
2697
2698	// Compile and execute a filtering function if one is not provided
2699	// Provide `match` to avoid retokenization if we modified the selector above
2700	( compiled || compile( selector, match ) )(
2701		seed,
2702		context,
2703		!documentIsHTML,
2704		results,
2705		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2706	);
2707	return results;
2708};
2709
2710// One-time assignments
2711
2712// Sort stability
2713support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2714
2715// Support: Chrome 14-35+
2716// Always assume duplicates if they aren't passed to the comparison function
2717support.detectDuplicates = !!hasDuplicate;
2718
2719// Initialize against the default document
2720setDocument();
2721
2722// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2723// Detached nodes confoundingly follow *each other*
2724support.sortDetached = assert(function( el ) {
2725	// Should return 1, but returns 4 (following)
2726	return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
2727});
2728
2729// Support: IE<8
2730// Prevent attribute/property "interpolation"
2731// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2732if ( !assert(function( el ) {
2733	el.innerHTML = "<a href='#'></a>";
2734	return el.firstChild.getAttribute("href") === "#" ;
2735}) ) {
2736	addHandle( "type|href|height|width", function( elem, name, isXML ) {
2737		if ( !isXML ) {
2738			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2739		}
2740	});
2741}
2742
2743// Support: IE<9
2744// Use defaultValue in place of getAttribute("value")
2745if ( !support.attributes || !assert(function( el ) {
2746	el.innerHTML = "<input/>";
2747	el.firstChild.setAttribute( "value", "" );
2748	return el.firstChild.getAttribute( "value" ) === "";
2749}) ) {
2750	addHandle( "value", function( elem, name, isXML ) {
2751		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2752			return elem.defaultValue;
2753		}
2754	});
2755}
2756
2757// Support: IE<9
2758// Use getAttributeNode to fetch booleans when getAttribute lies
2759if ( !assert(function( el ) {
2760	return el.getAttribute("disabled") == null;
2761}) ) {
2762	addHandle( booleans, function( elem, name, isXML ) {
2763		var val;
2764		if ( !isXML ) {
2765			return elem[ name ] === true ? name.toLowerCase() :
2766					(val = elem.getAttributeNode( name )) && val.specified ?
2767					val.value :
2768				null;
2769		}
2770	});
2771}
2772
2773return Sizzle;
2774
2775})( window );
2776
2777
2778
2779jQuery.find = Sizzle;
2780jQuery.expr = Sizzle.selectors;
2781
2782// Deprecated
2783jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2784jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
2785jQuery.text = Sizzle.getText;
2786jQuery.isXMLDoc = Sizzle.isXML;
2787jQuery.contains = Sizzle.contains;
2788jQuery.escapeSelector = Sizzle.escape;
2789
2790
2791
2792
2793var dir = function( elem, dir, until ) {
2794	var matched = [],
2795		truncate = until !== undefined;
2796
2797	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2798		if ( elem.nodeType === 1 ) {
2799			if ( truncate && jQuery( elem ).is( until ) ) {
2800				break;
2801			}
2802			matched.push( elem );
2803		}
2804	}
2805	return matched;
2806};
2807
2808
2809var siblings = function( n, elem ) {
2810	var matched = [];
2811
2812	for ( ; n; n = n.nextSibling ) {
2813		if ( n.nodeType === 1 && n !== elem ) {
2814			matched.push( n );
2815		}
2816	}
2817
2818	return matched;
2819};
2820
2821
2822var rneedsContext = jQuery.expr.match.needsContext;
2823
2824
2825
2826function nodeName( elem, name ) {
2827
2828  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
2829
2830};
2831var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
2832
2833
2834
2835// Implement the identical functionality for filter and not
2836function winnow( elements, qualifier, not ) {
2837	if ( isFunction( qualifier ) ) {
2838		return jQuery.grep( elements, function( elem, i ) {
2839			return !!qualifier.call( elem, i, elem ) !== not;
2840		} );
2841	}
2842
2843	// Single element
2844	if ( qualifier.nodeType ) {
2845		return jQuery.grep( elements, function( elem ) {
2846			return ( elem === qualifier ) !== not;
2847		} );
2848	}
2849
2850	// Arraylike of elements (jQuery, arguments, Array)
2851	if ( typeof qualifier !== "string" ) {
2852		return jQuery.grep( elements, function( elem ) {
2853			return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
2854		} );
2855	}
2856
2857	// Filtered directly for both simple and complex selectors
2858	return jQuery.filter( qualifier, elements, not );
2859}
2860
2861jQuery.filter = function( expr, elems, not ) {
2862	var elem = elems[ 0 ];
2863
2864	if ( not ) {
2865		expr = ":not(" + expr + ")";
2866	}
2867
2868	if ( elems.length === 1 && elem.nodeType === 1 ) {
2869		return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
2870	}
2871
2872	return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2873		return elem.nodeType === 1;
2874	} ) );
2875};
2876
2877jQuery.fn.extend( {
2878	find: function( selector ) {
2879		var i, ret,
2880			len = this.length,
2881			self = this;
2882
2883		if ( typeof selector !== "string" ) {
vendor: 4,662 bytes, lines 2884-3069
2884			return this.pushStack( jQuery( selector ).filter( function() {
2885				for ( i = 0; i < len; i++ ) {
2886					if ( jQuery.contains( self[ i ], this ) ) {
2887						return true;
2888					}
2889				}
2890			} ) );
2891		}
2892
2893		ret = this.pushStack( [] );
2894
2895		for ( i = 0; i < len; i++ ) {
2896			jQuery.find( selector, self[ i ], ret );
2897		}
2898
2899		return len > 1 ? jQuery.uniqueSort( ret ) : ret;
2900	},
2901	filter: function( selector ) {
2902		return this.pushStack( winnow( this, selector || [], false ) );
2903	},
2904	not: function( selector ) {
2905		return this.pushStack( winnow( this, selector || [], true ) );
2906	},
2907	is: function( selector ) {
2908		return !!winnow(
2909			this,
2910
2911			// If this is a positional/relative selector, check membership in the returned set
2912			// so $("p:first").is("p:last") won't return true for a doc with two "p".
2913			typeof selector === "string" && rneedsContext.test( selector ) ?
2914				jQuery( selector ) :
2915				selector || [],
2916			false
2917		).length;
2918	}
2919} );
2920
2921
2922// Initialize a jQuery object
2923
2924
2925// A central reference to the root jQuery(document)
2926var rootjQuery,
2927
2928	// A simple way to check for HTML strings
2929	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2930	// Strict HTML recognition (#11290: must start with <)
2931	// Shortcut simple #id case for speed
2932	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
2933
2934	init = jQuery.fn.init = function( selector, context, root ) {
2935		var match, elem;
2936
2937		// HANDLE: $(""), $(null), $(undefined), $(false)
2938		if ( !selector ) {
2939			return this;
2940		}
2941
2942		// Method init() accepts an alternate rootjQuery
2943		// so migrate can support jQuery.sub (gh-2101)
2944		root = root || rootjQuery;
2945
2946		// Handle HTML strings
2947		if ( typeof selector === "string" ) {
2948			if ( selector[ 0 ] === "<" &&
2949				selector[ selector.length - 1 ] === ">" &&
2950				selector.length >= 3 ) {
2951
2952				// Assume that strings that start and end with <> are HTML and skip the regex check
2953				match = [ null, selector, null ];
2954
2955			} else {
2956				match = rquickExpr.exec( selector );
2957			}
2958
2959			// Match html or make sure no context is specified for #id
2960			if ( match && ( match[ 1 ] || !context ) ) {
2961
2962				// HANDLE: $(html) -> $(array)
2963				if ( match[ 1 ] ) {
2964					context = context instanceof jQuery ? context[ 0 ] : context;
2965
2966					// Option to run scripts is true for back-compat
2967					// Intentionally let the error be thrown if parseHTML is not present
2968					jQuery.merge( this, jQuery.parseHTML(
2969						match[ 1 ],
2970						context && context.nodeType ? context.ownerDocument || context : document,
2971						true
2972					) );
2973
2974					// HANDLE: $(html, props)
2975					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
2976						for ( match in context ) {
2977
2978							// Properties of context are called as methods if possible
2979							if ( isFunction( this[ match ] ) ) {
2980								this[ match ]( context[ match ] );
2981
2982							// ...and otherwise set as attributes
2983							} else {
2984								this.attr( match, context[ match ] );
2985							}
2986						}
2987					}
2988
2989					return this;
2990
2991				// HANDLE: $(#id)
2992				} else {
2993					elem = document.getElementById( match[ 2 ] );
2994
2995					if ( elem ) {
2996
2997						// Inject the element directly into the jQuery object
2998						this[ 0 ] = elem;
2999						this.length = 1;
3000					}
3001					return this;
3002				}
3003
3004			// HANDLE: $(expr, $(...))
3005			} else if ( !context || context.jquery ) {
3006				return ( context || root ).find( selector );
3007
3008			// HANDLE: $(expr, context)
3009			// (which is just equivalent to: $(context).find(expr)
3010			} else {
3011				return this.constructor( context ).find( selector );
3012			}
3013
3014		// HANDLE: $(DOMElement)
3015		} else if ( selector.nodeType ) {
3016			this[ 0 ] = selector;
3017			this.length = 1;
3018			return this;
3019
3020		// HANDLE: $(function)
3021		// Shortcut for document ready
3022		} else if ( isFunction( selector ) ) {
3023			return root.ready !== undefined ?
3024				root.ready( selector ) :
3025
3026				// Execute immediately if ready is not present
3027				selector( jQuery );
3028		}
3029
3030		return jQuery.makeArray( selector, this );
3031	};
3032
3033// Give the init function the jQuery prototype for later instantiation
3034init.prototype = jQuery.fn;
3035
3036// Initialize central reference
3037rootjQuery = jQuery( document );
3038
3039
3040var rparentsprev = /^(?:parents|prev(?:Until|All))/,
3041
3042	// Methods guaranteed to produce a unique set when starting from a unique set
3043	guaranteedUnique = {
3044		children: true,
3045		contents: true,
3046		next: true,
3047		prev: true
3048	};
3049
3050jQuery.fn.extend( {
3051	has: function( target ) {
3052		var targets = jQuery( target, this ),
3053			l = targets.length;
3054
3055		return this.filter( function() {
3056			var i = 0;
3057			for ( ; i < l; i++ ) {
3058				if ( jQuery.contains( this, targets[ i ] ) ) {
3059					return true;
3060				}
3061			}
3062		} );
3063	},
3064
3065	closest: function( selectors, context ) {
3066		var cur,
3067			i = 0,
3068			l = this.length,
3069			matched = [],
vendor: 2,661 bytes, lines 3070-3172
3070			targets = typeof selectors !== "string" && jQuery( selectors );
3071
3072		// Positional selectors never match, since there's no _selection_ context
3073		if ( !rneedsContext.test( selectors ) ) {
3074			for ( ; i < l; i++ ) {
3075				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3076
3077					// Always skip document fragments
3078					if ( cur.nodeType < 11 && ( targets ?
3079						targets.index( cur ) > -1 :
3080
3081						// Don't pass non-elements to Sizzle
3082						cur.nodeType === 1 &&
3083							jQuery.find.matchesSelector( cur, selectors ) ) ) {
3084
3085						matched.push( cur );
3086						break;
3087					}
3088				}
3089			}
3090		}
3091
3092		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3093	},
3094
3095	// Determine the position of an element within the set
3096	index: function( elem ) {
3097
3098		// No argument, return index in parent
3099		if ( !elem ) {
3100			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3101		}
3102
3103		// Index in selector
3104		if ( typeof elem === "string" ) {
3105			return indexOf.call( jQuery( elem ), this[ 0 ] );
3106		}
3107
3108		// Locate the position of the desired element
3109		return indexOf.call( this,
3110
3111			// If it receives a jQuery object, the first element is used
3112			elem.jquery ? elem[ 0 ] : elem
3113		);
3114	},
3115
3116	add: function( selector, context ) {
3117		return this.pushStack(
3118			jQuery.uniqueSort(
3119				jQuery.merge( this.get(), jQuery( selector, context ) )
3120			)
3121		);
3122	},
3123
3124	addBack: function( selector ) {
3125		return this.add( selector == null ?
3126			this.prevObject : this.prevObject.filter( selector )
3127		);
3128	}
3129} );
3130
3131function sibling( cur, dir ) {
3132	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3133	return cur;
3134}
3135
3136jQuery.each( {
3137	parent: function( elem ) {
3138		var parent = elem.parentNode;
3139		return parent && parent.nodeType !== 11 ? parent : null;
3140	},
3141	parents: function( elem ) {
3142		return dir( elem, "parentNode" );
3143	},
3144	parentsUntil: function( elem, i, until ) {
3145		return dir( elem, "parentNode", until );
3146	},
3147	next: function( elem ) {
3148		return sibling( elem, "nextSibling" );
3149	},
3150	prev: function( elem ) {
3151		return sibling( elem, "previousSibling" );
3152	},
3153	nextAll: function( elem ) {
3154		return dir( elem, "nextSibling" );
3155	},
3156	prevAll: function( elem ) {
3157		return dir( elem, "previousSibling" );
3158	},
3159	nextUntil: function( elem, i, until ) {
3160		return dir( elem, "nextSibling", until );
3161	},
3162	prevUntil: function( elem, i, until ) {
3163		return dir( elem, "previousSibling", until );
3164	},
3165	siblings: function( elem ) {
3166		return siblings( ( elem.parentNode || {} ).firstChild, elem );
3167	},
3168	children: function( elem ) {
3169		return siblings( elem.firstChild );
3170	},
3171	contents: function( elem ) {
3172		if ( typeof elem.contentDocument !== "undefined" ) {
vendor: 8,463 bytes, lines 3172-3515
3172
3173			return elem.contentDocument;
3174		}
3175
3176		// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
3177		// Treat the template element as a regular one in browsers that
3178		// don't support it.
3179		if ( nodeName( elem, "template" ) ) {
3180			elem = elem.content || elem;
3181		}
3182
3183		return jQuery.merge( [], elem.childNodes );
3184	}
3185}, function( name, fn ) {
3186	jQuery.fn[ name ] = function( until, selector ) {
3187		var matched = jQuery.map( this, fn, until );
3188
3189		if ( name.slice( -5 ) !== "Until" ) {
3190			selector = until;
3191		}
3192
3193		if ( selector && typeof selector === "string" ) {
3194			matched = jQuery.filter( selector, matched );
3195		}
3196
3197		if ( this.length > 1 ) {
3198
3199			// Remove duplicates
3200			if ( !guaranteedUnique[ name ] ) {
3201				jQuery.uniqueSort( matched );
3202			}
3203
3204			// Reverse order for parents* and prev-derivatives
3205			if ( rparentsprev.test( name ) ) {
3206				matched.reverse();
3207			}
3208		}
3209
3210		return this.pushStack( matched );
3211	};
3212} );
3213var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
3214
3215
3216
3217// Convert String-formatted options into Object-formatted ones
3218function createOptions( options ) {
3219	var object = {};
3220	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
3221		object[ flag ] = true;
3222	} );
3223	return object;
3224}
3225
3226/*
3227 * Create a callback list using the following parameters:
3228 *
3229 *	options: an optional list of space-separated options that will change how
3230 *			the callback list behaves or a more traditional option object
3231 *
3232 * By default a callback list will act like an event callback list and can be
3233 * "fired" multiple times.
3234 *
3235 * Possible options:
3236 *
3237 *	once:			will ensure the callback list can only be fired once (like a Deferred)
3238 *
3239 *	memory:			will keep track of previous values and will call any callback added
3240 *					after the list has been fired right away with the latest "memorized"
3241 *					values (like a Deferred)
3242 *
3243 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
3244 *
3245 *	stopOnFalse:	interrupt callings when a callback returns false
3246 *
3247 */
3248jQuery.Callbacks = function( options ) {
3249
3250	// Convert options from String-formatted to Object-formatted if needed
3251	// (we check in cache first)
3252	options = typeof options === "string" ?
3253		createOptions( options ) :
3254		jQuery.extend( {}, options );
3255
3256	var // Flag to know if list is currently firing
3257		firing,
3258
3259		// Last fire value for non-forgettable lists
3260		memory,
3261
3262		// Flag to know if list was already fired
3263		fired,
3264
3265		// Flag to prevent firing
3266		locked,
3267
3268		// Actual callback list
3269		list = [],
3270
3271		// Queue of execution data for repeatable lists
3272		queue = [],
3273
3274		// Index of currently firing callback (modified by add/remove as needed)
3275		firingIndex = -1,
3276
3277		// Fire callbacks
3278		fire = function() {
3279
3280			// Enforce single-firing
3281			locked = locked || options.once;
3282
3283			// Execute callbacks for all pending executions,
3284			// respecting firingIndex overrides and runtime changes
3285			fired = firing = true;
3286			for ( ; queue.length; firingIndex = -1 ) {
3287				memory = queue.shift();
3288				while ( ++firingIndex < list.length ) {
3289
3290					// Run callback and check for early termination
3291					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3292						options.stopOnFalse ) {
3293
3294						// Jump to end and forget the data so .add doesn't re-fire
3295						firingIndex = list.length;
3296						memory = false;
3297					}
3298				}
3299			}
3300
3301			// Forget the data if we're done with it
3302			if ( !options.memory ) {
3303				memory = false;
3304			}
3305
3306			firing = false;
3307
3308			// Clean up if we're done firing for good
3309			if ( locked ) {
3310
3311				// Keep an empty list if we have data for future add calls
3312				if ( memory ) {
3313					list = [];
3314
3315				// Otherwise, this object is spent
3316				} else {
3317					list = "";
3318				}
3319			}
3320		},
3321
3322		// Actual Callbacks object
3323		self = {
3324
3325			// Add a callback or a collection of callbacks to the list
3326			add: function() {
3327				if ( list ) {
3328
3329					// If we have memory from a past run, we should fire after adding
3330					if ( memory && !firing ) {
3331						firingIndex = list.length - 1;
3332						queue.push( memory );
3333					}
3334
3335					( function add( args ) {
3336						jQuery.each( args, function( _, arg ) {
3337							if ( isFunction( arg ) ) {
3338								if ( !options.unique || !self.has( arg ) ) {
3339									list.push( arg );
3340								}
3341							} else if ( arg && arg.length && toType( arg ) !== "string" ) {
3342
3343								// Inspect recursively
3344								add( arg );
3345							}
3346						} );
3347					} )( arguments );
3348
3349					if ( memory && !firing ) {
3350						fire();
3351					}
3352				}
3353				return this;
3354			},
3355
3356			// Remove a callback from the list
3357			remove: function() {
3358				jQuery.each( arguments, function( _, arg ) {
3359					var index;
3360					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3361						list.splice( index, 1 );
3362
3363						// Handle firing indexes
3364						if ( index <= firingIndex ) {
3365							firingIndex--;
3366						}
3367					}
3368				} );
3369				return this;
3370			},
3371
3372			// Check if a given callback is in the list.
3373			// If no argument is given, return whether or not list has callbacks attached.
3374			has: function( fn ) {
3375				return fn ?
3376					jQuery.inArray( fn, list ) > -1 :
3377					list.length > 0;
3378			},
3379
3380			// Remove all callbacks from the list
3381			empty: function() {
3382				if ( list ) {
3383					list = [];
3384				}
3385				return this;
3386			},
3387
3388			// Disable .fire and .add
3389			// Abort any current/pending executions
3390			// Clear all callbacks and values
3391			disable: function() {
3392				locked = queue = [];
3393				list = memory = "";
3394				return this;
3395			},
3396			disabled: function() {
3397				return !list;
3398			},
3399
3400			// Disable .fire
3401			// Also disable .add unless we have memory (since it would have no effect)
3402			// Abort any pending executions
3403			lock: function() {
3404				locked = queue = [];
3405				if ( !memory && !firing ) {
3406					list = memory = "";
3407				}
3408				return this;
3409			},
3410			locked: function() {
3411				return !!locked;
3412			},
3413
3414			// Call all callbacks with the given context and arguments
3415			fireWith: function( context, args ) {
3416				if ( !locked ) {
3417					args = args || [];
3418					args = [ context, args.slice ? args.slice() : args ];
3419					queue.push( args );
3420					if ( !firing ) {
3421						fire();
3422					}
3423				}
3424				return this;
3425			},
3426
3427			// Call all the callbacks with the given arguments
3428			fire: function() {
3429				self.fireWith( this, arguments );
3430				return this;
3431			},
3432
3433			// To know if the callbacks have already been called at least once
3434			fired: function() {
3435				return !!fired;
3436			}
3437		};
3438
3439	return self;
3440};
3441
3442
3443function Identity( v ) {
3444	return v;
3445}
3446function Thrower( ex ) {
3447	throw ex;
3448}
3449
3450function adoptValue( value, resolve, reject, noValue ) {
3451	var method;
3452
3453	try {
3454
3455		// Check for promise aspect first to privilege synchronous behavior
3456		if ( value && isFunction( ( method = value.promise ) ) ) {
3457			method.call( value ).done( resolve ).fail( reject );
3458
3459		// Other thenables
3460		} else if ( value && isFunction( ( method = value.then ) ) ) {
3461			method.call( value, resolve, reject );
3462
3463		// Other non-thenables
3464		} else {
3465
3466			// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
3467			// * false: [ value ].slice( 0 ) => resolve( value )
3468			// * true: [ value ].slice( 1 ) => resolve()
3469			resolve.apply( undefined, [ value ].slice( noValue ) );
3470		}
3471
3472	// For Promises/A+, convert exceptions into rejections
3473	// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
3474	// Deferred#then to conditionally suppress rejection.
3475	} catch ( value ) {
3476
3477		// Support: Android 4.0 only
3478		// Strict mode functions invoked without .call/.apply get global-object context
3479		reject.apply( undefined, [ value ] );
3480	}
3481}
3482
3483jQuery.extend( {
3484
3485	Deferred: function( func ) {
3486		var tuples = [
3487
3488				// action, add listener, callbacks,
3489				// ... .then handlers, argument index, [final state]
3490				[ "notify", "progress", jQuery.Callbacks( "memory" ),
3491					jQuery.Callbacks( "memory" ), 2 ],
3492				[ "resolve", "done", jQuery.Callbacks( "once memory" ),
3493					jQuery.Callbacks( "once memory" ), 0, "resolved" ],
3494				[ "reject", "fail", jQuery.Callbacks( "once memory" ),
3495					jQuery.Callbacks( "once memory" ), 1, "rejected" ]
3496			],
3497			state = "pending",
3498			promise = {
3499				state: function() {
3500					return state;
3501				},
3502				always: function() {
3503					deferred.done( arguments ).fail( arguments );
3504					return this;
3505				},
3506				"catch": function( fn ) {
3507					return promise.then( null, fn );
3508				},
3509
3510				// Keep pipe for back-compat
3511				pipe: function( /* fnDone, fnFail, fnProgress */ ) {
3512					var fns = arguments;
3513
3514					return jQuery.Deferred( function( newDefer ) {
3515						jQuery.each( tuples, function( 
vendor: 14,915 bytes, lines 3515-4098
3515i, tuple ) {
3516
3517							// Map tuples (progress, done, fail) to arguments (done, fail, progress)
3518							var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
3519
3520							// deferred.progress(function() { bind to newDefer or newDefer.notify })
3521							// deferred.done(function() { bind to newDefer or newDefer.resolve })
3522							// deferred.fail(function() { bind to newDefer or newDefer.reject })
3523							deferred[ tuple[ 1 ] ]( function() {
3524								var returned = fn && fn.apply( this, arguments );
3525								if ( returned && isFunction( returned.promise ) ) {
3526									returned.promise()
3527										.progress( newDefer.notify )
3528										.done( newDefer.resolve )
3529										.fail( newDefer.reject );
3530								} else {
3531									newDefer[ tuple[ 0 ] + "With" ](
3532										this,
3533										fn ? [ returned ] : arguments
3534									);
3535								}
3536							} );
3537						} );
3538						fns = null;
3539					} ).promise();
3540				},
3541				then: function( onFulfilled, onRejected, onProgress ) {
3542					var maxDepth = 0;
3543					function resolve( depth, deferred, handler, special ) {
3544						return function() {
3545							var that = this,
3546								args = arguments,
3547								mightThrow = function() {
3548									var returned, then;
3549
3550									// Support: Promises/A+ section 2.3.3.3.3
3551									// https://promisesaplus.com/#point-59
3552									// Ignore double-resolution attempts
3553									if ( depth < maxDepth ) {
3554										return;
3555									}
3556
3557									returned = handler.apply( that, args );
3558
3559									// Support: Promises/A+ section 2.3.1
3560									// https://promisesaplus.com/#point-48
3561									if ( returned === deferred.promise() ) {
3562										throw new TypeError( "Thenable self-resolution" );
3563									}
3564
3565									// Support: Promises/A+ sections 2.3.3.1, 3.5
3566									// https://promisesaplus.com/#point-54
3567									// https://promisesaplus.com/#point-75
3568									// Retrieve `then` only once
3569									then = returned &&
3570
3571										// Support: Promises/A+ section 2.3.4
3572										// https://promisesaplus.com/#point-64
3573										// Only check objects and functions for thenability
3574										( typeof returned === "object" ||
3575											typeof returned === "function" ) &&
3576										returned.then;
3577
3578									// Handle a returned thenable
3579									if ( isFunction( then ) ) {
3580
3581										// Special processors (notify) just wait for resolution
3582										if ( special ) {
3583											then.call(
3584												returned,
3585												resolve( maxDepth, deferred, Identity, special ),
3586												resolve( maxDepth, deferred, Thrower, special )
3587											);
3588
3589										// Normal processors (resolve) also hook into progress
3590										} else {
3591
3592											// ...and disregard older resolution values
3593											maxDepth++;
3594
3595											then.call(
3596												returned,
3597												resolve( maxDepth, deferred, Identity, special ),
3598												resolve( maxDepth, deferred, Thrower, special ),
3599												resolve( maxDepth, deferred, Identity,
3600													deferred.notifyWith )
3601											);
3602										}
3603
3604									// Handle all other returned values
3605									} else {
3606
3607										// Only substitute handlers pass on context
3608										// and multiple values (non-spec behavior)
3609										if ( handler !== Identity ) {
3610											that = undefined;
3611											args = [ returned ];
3612										}
3613
3614										// Process the value(s)
3615										// Default process is resolve
3616										( special || deferred.resolveWith )( that, args );
3617									}
3618								},
3619
3620								// Only normal processors (resolve) catch and reject exceptions
3621								process = special ?
3622									mightThrow :
3623									function() {
3624										try {
3625											mightThrow();
3626										} catch ( e ) {
3627
3628											if ( jQuery.Deferred.exceptionHook ) {
3629												jQuery.Deferred.exceptionHook( e,
3630													process.stackTrace );
3631											}
3632
3633											// Support: Promises/A+ section 2.3.3.3.4.1
3634											// https://promisesaplus.com/#point-61
3635											// Ignore post-resolution exceptions
3636											if ( depth + 1 >= maxDepth ) {
3637
3638												// Only substitute handlers pass on context
3639												// and multiple values (non-spec behavior)
3640												if ( handler !== Thrower ) {
3641													that = undefined;
3642													args = [ e ];
3643												}
3644
3645												deferred.rejectWith( that, args );
3646											}
3647										}
3648									};
3649
3650							// Support: Promises/A+ section 2.3.3.3.1
3651							// https://promisesaplus.com/#point-57
3652							// Re-resolve promises immediately to dodge false rejection from
3653							// subsequent errors
3654							if ( depth ) {
3655								process();
3656							} else {
3657
3658								// Call an optional hook to record the stack, in case of exception
3659								// since it's otherwise lost when execution goes async
3660								if ( jQuery.Deferred.getStackHook ) {
3661									process.stackTrace = jQuery.Deferred.getStackHook();
3662								}
3663								window.setTimeout( process );
3664							}
3665						};
3666					}
3667
3668					return jQuery.Deferred( function( newDefer ) {
3669
3670						// progress_handlers.add( ... )
3671						tuples[ 0 ][ 3 ].add(
3672							resolve(
3673								0,
3674								newDefer,
3675								isFunction( onProgress ) ?
3676									onProgress :
3677									Identity,
3678								newDefer.notifyWith
3679							)
3680						);
3681
3682						// fulfilled_handlers.add( ... )
3683						tuples[ 1 ][ 3 ].add(
3684							resolve(
3685								0,
3686								newDefer,
3687								isFunction( onFulfilled ) ?
3688									onFulfilled :
3689									Identity
3690							)
3691						);
3692
3693						// rejected_handlers.add( ... )
3694						tuples[ 2 ][ 3 ].add(
3695							resolve(
3696								0,
3697								newDefer,
3698								isFunction( onRejected ) ?
3699									onRejected :
3700									Thrower
3701							)
3702						);
3703					} ).promise();
3704				},
3705
3706				// Get a promise for this deferred
3707				// If obj is provided, the promise aspect is added to the object
3708				promise: function( obj ) {
3709					return obj != null ? jQuery.extend( obj, promise ) : promise;
3710				}
3711			},
3712			deferred = {};
3713
3714		// Add list-specific methods
3715		jQuery.each( tuples, function( i, tuple ) {
3716			var list = tuple[ 2 ],
3717				stateString = tuple[ 5 ];
3718
3719			// promise.progress = list.add
3720			// promise.done = list.add
3721			// promise.fail = list.add
3722			promise[ tuple[ 1 ] ] = list.add;
3723
3724			// Handle state
3725			if ( stateString ) {
3726				list.add(
3727					function() {
3728
3729						// state = "resolved" (i.e., fulfilled)
3730						// state = "rejected"
3731						state = stateString;
3732					},
3733
3734					// rejected_callbacks.disable
3735					// fulfilled_callbacks.disable
3736					tuples[ 3 - i ][ 2 ].disable,
3737
3738					// rejected_handlers.disable
3739					// fulfilled_handlers.disable
3740					tuples[ 3 - i ][ 3 ].disable,
3741
3742					// progress_callbacks.lock
3743					tuples[ 0 ][ 2 ].lock,
3744
3745					// progress_handlers.lock
3746					tuples[ 0 ][ 3 ].lock
3747				);
3748			}
3749
3750			// progress_handlers.fire
3751			// fulfilled_handlers.fire
3752			// rejected_handlers.fire
3753			list.add( tuple[ 3 ].fire );
3754
3755			// deferred.notify = function() { deferred.notifyWith(...) }
3756			// deferred.resolve = function() { deferred.resolveWith(...) }
3757			// deferred.reject = function() { deferred.rejectWith(...) }
3758			deferred[ tuple[ 0 ] ] = function() {
3759				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
3760				return this;
3761			};
3762
3763			// deferred.notifyWith = list.fireWith
3764			// deferred.resolveWith = list.fireWith
3765			// deferred.rejectWith = list.fireWith
3766			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3767		} );
3768
3769		// Make the deferred a promise
3770		promise.promise( deferred );
3771
3772		// Call given func if any
3773		if ( func ) {
3774			func.call( deferred, deferred );
3775		}
3776
3777		// All done!
3778		return deferred;
3779	},
3780
3781	// Deferred helper
3782	when: function( singleValue ) {
3783		var
3784
3785			// count of uncompleted subordinates
3786			remaining = arguments.length,
3787
3788			// count of unprocessed arguments
3789			i = remaining,
3790
3791			// subordinate fulfillment data
3792			resolveContexts = Array( i ),
3793			resolveValues = slice.call( arguments ),
3794
3795			// the master Deferred
3796			master = jQuery.Deferred(),
3797
3798			// subordinate callback factory
3799			updateFunc = function( i ) {
3800				return function( value ) {
3801					resolveContexts[ i ] = this;
3802					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3803					if ( !( --remaining ) ) {
3804						master.resolveWith( resolveContexts, resolveValues );
3805					}
3806				};
3807			};
3808
3809		// Single- and empty arguments are adopted like Promise.resolve
3810		if ( remaining <= 1 ) {
3811			adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
3812				!remaining );
3813
3814			// Use .then() to unwrap secondary thenables (cf. gh-3000)
3815			if ( master.state() === "pending" ||
3816				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
3817
3818				return master.then();
3819			}
3820		}
3821
3822		// Multiple arguments are aggregated like Promise.all array elements
3823		while ( i-- ) {
3824			adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
3825		}
3826
3827		return master.promise();
3828	}
3829} );
3830
3831
3832// These usually indicate a programmer mistake during development,
3833// warn about them ASAP rather than swallowing them by default.
3834var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
3835
3836jQuery.Deferred.exceptionHook = function( error, stack ) {
3837
3838	// Support: IE 8 - 9 only
3839	// Console exists when dev tools are open, which can happen at any time
3840	if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
3841		window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
3842	}
3843};
3844
3845
3846
3847
3848jQuery.readyException = function( error ) {
3849	window.setTimeout( function() {
3850		throw error;
3851	} );
3852};
3853
3854
3855
3856
3857// The deferred used on DOM ready
3858var readyList = jQuery.Deferred();
3859
3860jQuery.fn.ready = function( fn ) {
3861
3862	readyList
3863		.then( fn )
3864
3865		// Wrap jQuery.readyException in a function so that the lookup
3866		// happens at the time of error handling instead of callback
3867		// registration.
3868		.catch( function( error ) {
3869			jQuery.readyException( error );
3870		} );
3871
3872	return this;
3873};
3874
3875jQuery.extend( {
3876
3877	// Is the DOM ready to be used? Set to true once it occurs.
3878	isReady: false,
3879
3880	// A counter to track how many items to wait for before
3881	// the ready event fires. See #6781
3882	readyWait: 1,
3883
3884	// Handle when the DOM is ready
3885	ready: function( wait ) {
3886
3887		// Abort if there are pending holds or we're already ready
3888		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3889			return;
3890		}
3891
3892		// Remember that the DOM is ready
3893		jQuery.isReady = true;
3894
3895		// If a normal DOM Ready event fired, decrement, and wait if need be
3896		if ( wait !== true && --jQuery.readyWait > 0 ) {
3897			return;
3898		}
3899
3900		// If there are functions bound, to execute
3901		readyList.resolveWith( document, [ jQuery ] );
3902	}
3903} );
3904
3905jQuery.ready.then = readyList.then;
3906
3907// The ready event handler and self cleanup method
3908function completed() {
3909	document.removeEventListener( "DOMContentLoaded", completed );
3910	window.removeEventListener( "load", completed );
3911	jQuery.ready();
3912}
3913
3914// Catch cases where $(document).ready() is called
3915// after the browser event has already occurred.
3916// Support: IE <=9 - 10 only
3917// Older IE sometimes signals "interactive" too soon
3918if ( document.readyState === "complete" ||
3919	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3920
3921	// Handle it asynchronously to allow scripts the opportunity to delay ready
3922	window.setTimeout( jQuery.ready );
3923
3924} else {
3925
3926	// Use the handy event callback
3927	document.addEventListener( "DOMContentLoaded", completed );
3928
3929	// A fallback to window.onload, that will always work
3930	window.addEventListener( "load", completed );
3931}
3932
3933
3934
3935
3936// Multifunctional method to get and set values of a collection
3937// The value/s can optionally be executed if it's a function
3938var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3939	var i = 0,
3940		len = elems.length,
3941		bulk = key == null;
3942
3943	// Sets many values
3944	if ( toType( key ) === "object" ) {
3945		chainable = true;
3946		for ( i in key ) {
3947			access( elems, fn, i, key[ i ], true, emptyGet, raw );
3948		}
3949
3950	// Sets one value
3951	} else if ( value !== undefined ) {
3952		chainable = true;
3953
3954		if ( !isFunction( value ) ) {
3955			raw = true;
3956		}
3957
3958		if ( bulk ) {
3959
3960			// Bulk operations run against the entire set
3961			if ( raw ) {
3962				fn.call( elems, value );
3963				fn = null;
3964
3965			// ...except when executing function values
3966			} else {
3967				bulk = fn;
3968				fn = function( elem, key, value ) {
3969					return bulk.call( jQuery( elem ), value );
3970				};
3971			}
3972		}
3973
3974		if ( fn ) {
3975			for ( ; i < len; i++ ) {
3976				fn(
3977					elems[ i ], key, raw ?
3978					value :
3979					value.call( elems[ i ], i, fn( elems[ i ], key ) )
3980				);
3981			}
3982		}
3983	}
3984
3985	if ( chainable ) {
3986		return elems;
3987	}
3988
3989	// Gets
3990	if ( bulk ) {
3991		return fn.call( elems );
3992	}
3993
3994	return len ? fn( elems[ 0 ], key ) : emptyGet;
3995};
3996
3997
3998// Matches dashed string for camelizing
3999var rmsPrefix = /^-ms-/,
4000	rdashAlpha = /-([a-z])/g;
4001
4002// Used by camelCase as callback to replace()
4003function fcamelCase( all, letter ) {
4004	return letter.toUpperCase();
4005}
4006
4007// Convert dashed to camelCase; used by the css and data modules
4008// Support: IE <=9 - 11, Edge 12 - 15
4009// Microsoft forgot to hump their vendor prefix (#9572)
4010function camelCase( string ) {
4011	return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
4012}
4013var acceptData = function( owner ) {
4014
4015	// Accepts only:
4016	//  - Node
4017	//    - Node.ELEMENT_NODE
4018	//    - Node.DOCUMENT_NODE
4019	//  - Object
4020	//    - Any
4021	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
4022};
4023
4024
4025
4026
4027function Data() {
4028	this.expando = jQuery.expando + Data.uid++;
4029}
4030
4031Data.uid = 1;
4032
4033Data.prototype = {
4034
4035	cache: function( owner ) {
4036
4037		// Check if the owner object already has a cache
4038		var value = owner[ this.expando ];
4039
4040		// If not, create one
4041		if ( !value ) {
4042			value = {};
4043
4044			// We can accept data for non-element nodes in modern browsers,
4045			// but we should not, see #8335.
4046			// Always return an empty object.
4047			if ( acceptData( owner ) ) {
4048
4049				// If it is a node unlikely to be stringify-ed or looped over
4050				// use plain assignment
4051				if ( owner.nodeType ) {
4052					owner[ this.expando ] = value;
4053
4054				// Otherwise secure it in a non-enumerable property
4055				// configurable must be true to allow the property to be
4056				// deleted when data is removed
4057				} else {
4058					Object.defineProperty( owner, this.expando, {
4059						value: value,
4060						configurable: true
4061					} );
4062				}
4063			}
4064		}
4065
4066		return value;
4067	},
4068	set: function( owner, data, value ) {
4069		var prop,
4070			cache = this.cache( owner );
4071
4072		// Handle: [ owner, key, value ] args
4073		// Always use camelCase key (gh-2257)
4074		if ( typeof data === "string" ) {
4075			cache[ camelCase( data ) ] = value;
4076
4077		// Handle: [ owner, { properties } ] args
4078		} else {
4079
4080			// Copy the properties one-by-one to the cache object
4081			for ( prop in data ) {
4082				cache[ camelCase( prop ) ] = data[ prop ];
4083			}
4084		}
4085		return cache;
4086	},
4087	get: function( owner, key ) {
4088		return key === undefined ?
4089			this.cache( owner ) :
4090
4091			// Always use camelCase key (gh-2257)
4092			owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
4093	},
4094	access: function( owner, key, value ) {
4095
4096		// In cases where either:
4097		//
4098		//   1. No key was specified
vendor: 8,694 bytes, lines 4099-4457
4099		//   2. A string key was specified, but no value provided
4100		//
4101		// Take the "read" path and allow the get method to determine
4102		// which value to return, respectively either:
4103		//
4104		//   1. The entire cache object
4105		//   2. The data stored at the key
4106		//
4107		if ( key === undefined ||
4108				( ( key && typeof key === "string" ) && value === undefined ) ) {
4109
4110			return this.get( owner, key );
4111		}
4112
4113		// When the key is not a string, or both a key and value
4114		// are specified, set or extend (existing objects) with either:
4115		//
4116		//   1. An object of properties
4117		//   2. A key and value
4118		//
4119		this.set( owner, key, value );
4120
4121		// Since the "set" path can have two possible entry points
4122		// return the expected data based on which path was taken[*]
4123		return value !== undefined ? value : key;
4124	},
4125	remove: function( owner, key ) {
4126		var i,
4127			cache = owner[ this.expando ];
4128
4129		if ( cache === undefined ) {
4130			return;
4131		}
4132
4133		if ( key !== undefined ) {
4134
4135			// Support array or space separated string of keys
4136			if ( Array.isArray( key ) ) {
4137
4138				// If key is an array of keys...
4139				// We always set camelCase keys, so remove that.
4140				key = key.map( camelCase );
4141			} else {
4142				key = camelCase( key );
4143
4144				// If a key with the spaces exists, use it.
4145				// Otherwise, create an array by matching non-whitespace
4146				key = key in cache ?
4147					[ key ] :
4148					( key.match( rnothtmlwhite ) || [] );
4149			}
4150
4151			i = key.length;
4152
4153			while ( i-- ) {
4154				delete cache[ key[ i ] ];
4155			}
4156		}
4157
4158		// Remove the expando if there's no more data
4159		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
4160
4161			// Support: Chrome <=35 - 45
4162			// Webkit & Blink performance suffers when deleting properties
4163			// from DOM nodes, so set to undefined instead
4164			// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
4165			if ( owner.nodeType ) {
4166				owner[ this.expando ] = undefined;
4167			} else {
4168				delete owner[ this.expando ];
4169			}
4170		}
4171	},
4172	hasData: function( owner ) {
4173		var cache = owner[ this.expando ];
4174		return cache !== undefined && !jQuery.isEmptyObject( cache );
4175	}
4176};
4177var dataPriv = new Data();
4178
4179var dataUser = new Data();
4180
4181
4182
4183//	Implementation Summary
4184//
4185//	1. Enforce API surface and semantic compatibility with 1.9.x branch
4186//	2. Improve the module's maintainability by reducing the storage
4187//		paths to a single mechanism.
4188//	3. Use the same single mechanism to support "private" and "user" data.
4189//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
4190//	5. Avoid exposing implementation details on user objects (eg. expando properties)
4191//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
4192
4193var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
4194	rmultiDash = /[A-Z]/g;
4195
4196function getData( data ) {
4197	if ( data === "true" ) {
4198		return true;
4199	}
4200
4201	if ( data === "false" ) {
4202		return false;
4203	}
4204
4205	if ( data === "null" ) {
4206		return null;
4207	}
4208
4209	// Only convert to a number if it doesn't change the string
4210	if ( data === +data + "" ) {
4211		return +data;
4212	}
4213
4214	if ( rbrace.test( data ) ) {
4215		return JSON.parse( data );
4216	}
4217
4218	return data;
4219}
4220
4221function dataAttr( elem, key, data ) {
4222	var name;
4223
4224	// If nothing was found internally, try to fetch any
4225	// data from the HTML5 data-* attribute
4226	if ( data === undefined && elem.nodeType === 1 ) {
4227		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
4228		data = elem.getAttribute( name );
4229
4230		if ( typeof data === "string" ) {
4231			try {
4232				data = getData( data );
4233			} catch ( e ) {}
4234
4235			// Make sure we set the data so it isn't changed later
4236			dataUser.set( elem, key, data );
4237		} else {
4238			data = undefined;
4239		}
4240	}
4241	return data;
4242}
4243
4244jQuery.extend( {
4245	hasData: function( elem ) {
4246		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
4247	},
4248
4249	data: function( elem, name, data ) {
4250		return dataUser.access( elem, name, data );
4251	},
4252
4253	removeData: function( elem, name ) {
4254		dataUser.remove( elem, name );
4255	},
4256
4257	// TODO: Now that all calls to _data and _removeData have been replaced
4258	// with direct calls to dataPriv methods, these can be deprecated.
4259	_data: function( elem, name, data ) {
4260		return dataPriv.access( elem, name, data );
4261	},
4262
4263	_removeData: function( elem, name ) {
4264		dataPriv.remove( elem, name );
4265	}
4266} );
4267
4268jQuery.fn.extend( {
4269	data: function( key, value ) {
4270		var i, name, data,
4271			elem = this[ 0 ],
4272			attrs = elem && elem.attributes;
4273
4274		// Gets all values
4275		if ( key === undefined ) {
4276			if ( this.length ) {
4277				data = dataUser.get( elem );
4278
4279				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4280					i = attrs.length;
4281					while ( i-- ) {
4282
4283						// Support: IE 11 only
4284						// The attrs elements can be null (#14894)
4285						if ( attrs[ i ] ) {
4286							name = attrs[ i ].name;
4287							if ( name.indexOf( "data-" ) === 0 ) {
4288								name = camelCase( name.slice( 5 ) );
4289								dataAttr( elem, name, data[ name ] );
4290							}
4291						}
4292					}
4293					dataPriv.set( elem, "hasDataAttrs", true );
4294				}
4295			}
4296
4297			return data;
4298		}
4299
4300		// Sets multiple values
4301		if ( typeof key === "object" ) {
4302			return this.each( function() {
4303				dataUser.set( this, key );
4304			} );
4305		}
4306
4307		return access( this, function( value ) {
4308			var data;
4309
4310			// The calling jQuery object (element matches) is not empty
4311			// (and therefore has an element appears at this[ 0 ]) and the
4312			// `value` parameter was not undefined. An empty jQuery object
4313			// will result in `undefined` for elem = this[ 0 ] which will
4314			// throw an exception if an attempt to read a data cache is made.
4315			if ( elem && value === undefined ) {
4316
4317				// Attempt to get data from the cache
4318				// The key will always be camelCased in Data
4319				data = dataUser.get( elem, key );
4320				if ( data !== undefined ) {
4321					return data;
4322				}
4323
4324				// Attempt to "discover" the data in
4325				// HTML5 custom data-* attrs
4326				data = dataAttr( elem, key );
4327				if ( data !== undefined ) {
4328					return data;
4329				}
4330
4331				// We tried really hard, but the data doesn't exist.
4332				return;
4333			}
4334
4335			// Set the data...
4336			this.each( function() {
4337
4338				// We always store the camelCased key
4339				dataUser.set( this, key, value );
4340			} );
4341		}, null, value, arguments.length > 1, null, true );
4342	},
4343
4344	removeData: function( key ) {
4345		return this.each( function() {
4346			dataUser.remove( this, key );
4347		} );
4348	}
4349} );
4350
4351
4352jQuery.extend( {
4353	queue: function( elem, type, data ) {
4354		var queue;
4355
4356		if ( elem ) {
4357			type = ( type || "fx" ) + "queue";
4358			queue = dataPriv.get( elem, type );
4359
4360			// Speed up dequeue by getting out quickly if this is just a lookup
4361			if ( data ) {
4362				if ( !queue || Array.isArray( data ) ) {
4363					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
4364				} else {
4365					queue.push( data );
4366				}
4367			}
4368			return queue || [];
4369		}
4370	},
4371
4372	dequeue: function( elem, type ) {
4373		type = type || "fx";
4374
4375		var queue = jQuery.queue( elem, type ),
4376			startLength = queue.length,
4377			fn = queue.shift(),
4378			hooks = jQuery._queueHooks( elem, type ),
4379			next = function() {
4380				jQuery.dequeue( elem, type );
4381			};
4382
4383		// If the fx queue is dequeued, always remove the progress sentinel
4384		if ( fn === "inprogress" ) {
4385			fn = queue.shift();
4386			startLength--;
4387		}
4388
4389		if ( fn ) {
4390
4391			// Add a progress sentinel to prevent the fx queue from being
4392			// automatically dequeued
4393			if ( type === "fx" ) {
4394				queue.unshift( "inprogress" );
4395			}
4396
4397			// Clear up the last queue stop function
4398			delete hooks.stop;
4399			fn.call( elem, next, hooks );
4400		}
4401
4402		if ( !startLength && hooks ) {
4403			hooks.empty.fire();
4404		}
4405	},
4406
4407	// Not public - generate a queueHooks object, or return the current one
4408	_queueHooks: function( elem, type ) {
4409		var key = type + "queueHooks";
4410		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
4411			empty: jQuery.Callbacks( "once memory" ).add( function() {
4412				dataPriv.remove( elem, [ type + "queue", key ] );
4413			} )
4414		} );
4415	}
4416} );
4417
4418jQuery.fn.extend( {
4419	queue: function( type, data ) {
4420		var setter = 2;
4421
4422		if ( typeof type !== "string" ) {
4423			data = type;
4424			type = "fx";
4425			setter--;
4426		}
4427
4428		if ( arguments.length < setter ) {
4429			return jQuery.queue( this[ 0 ], type );
4430		}
4431
4432		return data === undefined ?
4433			this :
4434			this.each( function() {
4435				var queue = jQuery.queue( this, type, data );
4436
4437				// Ensure a hooks for this queue
4438				jQuery._queueHooks( this, type );
4439
4440				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4441					jQuery.dequeue( this, type );
4442				}
4443			} );
4444	},
4445	dequeue: function( type ) {
4446		return this.each( function() {
4447			jQuery.dequeue( this, type );
4448		} );
4449	},
4450	clearQueue: function( type ) {
4451		return this.queue( type || "fx", [] );
4452	},
4453
4454	// Get a promise resolved when queues of a certain type
4455	// are emptied (fx is the type by default)
4456	promise: function( type, obj ) {
4457		var tmp,
vendor: 10,491 bytes, lines 4458-4882
4458			count = 1,
4459			defer = jQuery.Deferred(),
4460			elements = this,
4461			i = this.length,
4462			resolve = function() {
4463				if ( !( --count ) ) {
4464					defer.resolveWith( elements, [ elements ] );
4465				}
4466			};
4467
4468		if ( typeof type !== "string" ) {
4469			obj = type;
4470			type = undefined;
4471		}
4472		type = type || "fx";
4473
4474		while ( i-- ) {
4475			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
4476			if ( tmp && tmp.empty ) {
4477				count++;
4478				tmp.empty.add( resolve );
4479			}
4480		}
4481		resolve();
4482		return defer.promise( obj );
4483	}
4484} );
4485var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4486
4487var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4488
4489
4490var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4491
4492var documentElement = document.documentElement;
4493
4494
4495
4496	var isAttached = function( elem ) {
4497			return jQuery.contains( elem.ownerDocument, elem );
4498		},
4499		composed = { composed: true };
4500
4501	// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
4502	// Check attachment across shadow DOM boundaries when possible (gh-3504)
4503	// Support: iOS 10.0-10.2 only
4504	// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
4505	// leading to errors. We need to check for `getRootNode`.
4506	if ( documentElement.getRootNode ) {
4507		isAttached = function( elem ) {
4508			return jQuery.contains( elem.ownerDocument, elem ) ||
4509				elem.getRootNode( composed ) === elem.ownerDocument;
4510		};
4511	}
4512var isHiddenWithinTree = function( elem, el ) {
4513
4514		// isHiddenWithinTree might be called from jQuery#filter function;
4515		// in that case, element will be second argument
4516		elem = el || elem;
4517
4518		// Inline style trumps all
4519		return elem.style.display === "none" ||
4520			elem.style.display === "" &&
4521
4522			// Otherwise, check computed style
4523			// Support: Firefox <=43 - 45
4524			// Disconnected elements can have computed display: none, so first confirm that elem is
4525			// in the document.
4526			isAttached( elem ) &&
4527
4528			jQuery.css( elem, "display" ) === "none";
4529	};
4530
4531var swap = function( elem, options, callback, args ) {
4532	var ret, name,
4533		old = {};
4534
4535	// Remember the old values, and insert the new ones
4536	for ( name in options ) {
4537		old[ name ] = elem.style[ name ];
4538		elem.style[ name ] = options[ name ];
4539	}
4540
4541	ret = callback.apply( elem, args || [] );
4542
4543	// Revert the old values
4544	for ( name in options ) {
4545		elem.style[ name ] = old[ name ];
4546	}
4547
4548	return ret;
4549};
4550
4551
4552
4553
4554function adjustCSS( elem, prop, valueParts, tween ) {
4555	var adjusted, scale,
4556		maxIterations = 20,
4557		currentValue = tween ?
4558			function() {
4559				return tween.cur();
4560			} :
4561			function() {
4562				return jQuery.css( elem, prop, "" );
4563			},
4564		initial = currentValue(),
4565		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4566
4567		// Starting value computation is required for potential unit mismatches
4568		initialInUnit = elem.nodeType &&
4569			( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4570			rcssNum.exec( jQuery.css( elem, prop ) );
4571
4572	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4573
4574		// Support: Firefox <=54
4575		// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
4576		initial = initial / 2;
4577
4578		// Trust units reported by jQuery.css
4579		unit = unit || initialInUnit[ 3 ];
4580
4581		// Iteratively approximate from a nonzero starting point
4582		initialInUnit = +initial || 1;
4583
4584		while ( maxIterations-- ) {
4585
4586			// Evaluate and update our best guess (doubling guesses that zero out).
4587			// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
4588			jQuery.style( elem, prop, initialInUnit + unit );
4589			if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
4590				maxIterations = 0;
4591			}
4592			initialInUnit = initialInUnit / scale;
4593
4594		}
4595
4596		initialInUnit = initialInUnit * 2;
4597		jQuery.style( elem, prop, initialInUnit + unit );
4598
4599		// Make sure we update the tween properties later on
4600		valueParts = valueParts || [];
4601	}
4602
4603	if ( valueParts ) {
4604		initialInUnit = +initialInUnit || +initial || 0;
4605
4606		// Apply relative offset (+=/-=) if specified
4607		adjusted = valueParts[ 1 ] ?
4608			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4609			+valueParts[ 2 ];
4610		if ( tween ) {
4611			tween.unit = unit;
4612			tween.start = initialInUnit;
4613			tween.end = adjusted;
4614		}
4615	}
4616	return adjusted;
4617}
4618
4619
4620var defaultDisplayMap = {};
4621
4622function getDefaultDisplay( elem ) {
4623	var temp,
4624		doc = elem.ownerDocument,
4625		nodeName = elem.nodeName,
4626		display = defaultDisplayMap[ nodeName ];
4627
4628	if ( display ) {
4629		return display;
4630	}
4631
4632	temp = doc.body.appendChild( doc.createElement( nodeName ) );
4633	display = jQuery.css( temp, "display" );
4634
4635	temp.parentNode.removeChild( temp );
4636
4637	if ( display === "none" ) {
4638		display = "block";
4639	}
4640	defaultDisplayMap[ nodeName ] = display;
4641
4642	return display;
4643}
4644
4645function showHide( elements, show ) {
4646	var display, elem,
4647		values = [],
4648		index = 0,
4649		length = elements.length;
4650
4651	// Determine new display value for elements that need to change
4652	for ( ; index < length; index++ ) {
4653		elem = elements[ index ];
4654		if ( !elem.style ) {
4655			continue;
4656		}
4657
4658		display = elem.style.display;
4659		if ( show ) {
4660
4661			// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
4662			// check is required in this first loop unless we have a nonempty display value (either
4663			// inline or about-to-be-restored)
4664			if ( display === "none" ) {
4665				values[ index ] = dataPriv.get( elem, "display" ) || null;
4666				if ( !values[ index ] ) {
4667					elem.style.display = "";
4668				}
4669			}
4670			if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
4671				values[ index ] = getDefaultDisplay( elem );
4672			}
4673		} else {
4674			if ( display !== "none" ) {
4675				values[ index ] = "none";
4676
4677				// Remember what we're overwriting
4678				dataPriv.set( elem, "display", display );
4679			}
4680		}
4681	}
4682
4683	// Set the display of the elements in a second loop to avoid constant reflow
4684	for ( index = 0; index < length; index++ ) {
4685		if ( values[ index ] != null ) {
4686			elements[ index ].style.display = values[ index ];
4687		}
4688	}
4689
4690	return elements;
4691}
4692
4693jQuery.fn.extend( {
4694	show: function() {
4695		return showHide( this, true );
4696	},
4697	hide: function() {
4698		return showHide( this );
4699	},
4700	toggle: function( state ) {
4701		if ( typeof state === "boolean" ) {
4702			return state ? this.show() : this.hide();
4703		}
4704
4705		return this.each( function() {
4706			if ( isHiddenWithinTree( this ) ) {
4707				jQuery( this ).show();
4708			} else {
4709				jQuery( this ).hide();
4710			}
4711		} );
4712	}
4713} );
4714var rcheckableType = ( /^(?:checkbox|radio)$/i );
4715
4716var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
4717
4718var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
4719
4720
4721
4722// We have to close these tags to support XHTML (#13200)
4723var wrapMap = {
4724
4725	// Support: IE <=9 only
4726	option: [ 1, "<select multiple='multiple'>", "</select>" ],
4727
4728	// XHTML parsers do not magically insert elements in the
4729	// same way that tag soup parsers do. So we cannot shorten
4730	// this by omitting <tbody> or other required elements.
4731	thead: [ 1, "<table>", "</table>" ],
4732	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4733	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4734	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4735
4736	_default: [ 0, "", "" ]
4737};
4738
4739// Support: IE <=9 only
4740wrapMap.optgroup = wrapMap.option;
4741
4742wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4743wrapMap.th = wrapMap.td;
4744
4745
4746function getAll( context, tag ) {
4747
4748	// Support: IE <=9 - 11 only
4749	// Use typeof to avoid zero-argument method invocation on host objects (#15151)
4750	var ret;
4751
4752	if ( typeof context.getElementsByTagName !== "undefined" ) {
4753		ret = context.getElementsByTagName( tag || "*" );
4754
4755	} else if ( typeof context.querySelectorAll !== "undefined" ) {
4756		ret = context.querySelectorAll( tag || "*" );
4757
4758	} else {
4759		ret = [];
4760	}
4761
4762	if ( tag === undefined || tag && nodeName( context, tag ) ) {
4763		return jQuery.merge( [ context ], ret );
4764	}
4765
4766	return ret;
4767}
4768
4769
4770// Mark scripts as having already been evaluated
4771function setGlobalEval( elems, refElements ) {
4772	var i = 0,
4773		l = elems.length;
4774
4775	for ( ; i < l; i++ ) {
4776		dataPriv.set(
4777			elems[ i ],
4778			"globalEval",
4779			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
4780		);
4781	}
4782}
4783
4784
4785var rhtml = /<|&#?\w+;/;
4786
4787function buildFragment( elems, context, scripts, selection, ignored ) {
4788	var elem, tmp, tag, wrap, attached, j,
4789		fragment = context.createDocumentFragment(),
4790		nodes = [],
4791		i = 0,
4792		l = elems.length;
4793
4794	for ( ; i < l; i++ ) {
4795		elem = elems[ i ];
4796
4797		if ( elem || elem === 0 ) {
4798
4799			// Add nodes directly
4800			if ( toType( elem ) === "object" ) {
4801
4802				// Support: Android <=4.0 only, PhantomJS 1 only
4803				// push.apply(_, arraylike) throws on ancient WebKit
4804				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4805
4806			// Convert non-html into a text node
4807			} else if ( !rhtml.test( elem ) ) {
4808				nodes.push( context.createTextNode( elem ) );
4809
4810			// Convert html into DOM nodes
4811			} else {
4812				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
4813
4814				// Deserialize a standard representation
4815				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4816				wrap = wrapMap[ tag ] || wrapMap._default;
4817				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4818
4819				// Descend through wrappers to the right content
4820				j = wrap[ 0 ];
4821				while ( j-- ) {
4822					tmp = tmp.lastChild;
4823				}
4824
4825				// Support: Android <=4.0 only, PhantomJS 1 only
4826				// push.apply(_, arraylike) throws on ancient WebKit
4827				jQuery.merge( nodes, tmp.childNodes );
4828
4829				// Remember the top-level container
4830				tmp = fragment.firstChild;
4831
4832				// Ensure the created nodes are orphaned (#12392)
4833				tmp.textContent = "";
4834			}
4835		}
4836	}
4837
4838	// Remove wrapper from fragment
4839	fragment.textContent = "";
4840
4841	i = 0;
4842	while ( ( elem = nodes[ i++ ] ) ) {
4843
4844		// Skip elements already in the context collection (trac-4087)
4845		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4846			if ( ignored ) {
4847				ignored.push( elem );
4848			}
4849			continue;
4850		}
4851
4852		attached = isAttached( elem );
4853
4854		// Append to fragment
4855		tmp = getAll( fragment.appendChild( elem ), "script" );
4856
4857		// Preserve script evaluation history
4858		if ( attached ) {
4859			setGlobalEval( tmp );
4860		}
4861
4862		// Capture executables
4863		if ( scripts ) {
4864			j = 0;
4865			while ( ( elem = tmp[ j++ ] ) ) {
4866				if ( rscriptType.test( elem.type || "" ) ) {
4867					scripts.push( elem );
4868				}
4869			}
4870		}
4871	}
4872
4873	return fragment;
4874}
4875
4876
4877( function() {
4878	var fragment = document.createDocumentFragment(),
4879		div = fragment.appendChild( document.createElement( "div" ) ),
4880		input = document.createElement( "input" );
4881
4882	// Support: Android 4.0 - 4.3 only
vendor: 11,062 bytes, lines 4883-5265
4883	// Check state lost if the name is set (#11217)
4884	// Support: Windows Web Apps (WWA)
4885	// `name` and `type` must use .setAttribute for WWA (#14901)
4886	input.setAttribute( "type", "radio" );
4887	input.setAttribute( "checked", "checked" );
4888	input.setAttribute( "name", "t" );
4889
4890	div.appendChild( input );
4891
4892	// Support: Android <=4.1 only
4893	// Older WebKit doesn't clone checked state correctly in fragments
4894	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4895
4896	// Support: IE <=11 only
4897	// Make sure textarea (and checkbox) defaultValue is properly cloned
4898	div.innerHTML = "<textarea>x</textarea>";
4899	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4900} )();
4901
4902
4903var
4904	rkeyEvent = /^key/,
4905	rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
4906	rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4907
4908function returnTrue() {
4909	return true;
4910}
4911
4912function returnFalse() {
4913	return false;
4914}
4915
4916// Support: IE <=9 - 11+
4917// focus() and blur() are asynchronous, except when they are no-op.
4918// So expect focus to be synchronous when the element is already active,
4919// and blur to be synchronous when the element is not already active.
4920// (focus and blur are always synchronous in other supported browsers,
4921// this just defines when we can count on it).
4922function expectSync( elem, type ) {
4923	return ( elem === safeActiveElement() ) === ( type === "focus" );
4924}
4925
4926// Support: IE <=9 only
4927// Accessing document.activeElement can throw unexpectedly
4928// https://bugs.jquery.com/ticket/13393
4929function safeActiveElement() {
4930	try {
4931		return document.activeElement;
4932	} catch ( err ) { }
4933}
4934
4935function on( elem, types, selector, data, fn, one ) {
4936	var origFn, type;
4937
4938	// Types can be a map of types/handlers
4939	if ( typeof types === "object" ) {
4940
4941		// ( types-Object, selector, data )
4942		if ( typeof selector !== "string" ) {
4943
4944			// ( types-Object, data )
4945			data = data || selector;
4946			selector = undefined;
4947		}
4948		for ( type in types ) {
4949			on( elem, type, selector, data, types[ type ], one );
4950		}
4951		return elem;
4952	}
4953
4954	if ( data == null && fn == null ) {
4955
4956		// ( types, fn )
4957		fn = selector;
4958		data = selector = undefined;
4959	} else if ( fn == null ) {
4960		if ( typeof selector === "string" ) {
4961
4962			// ( types, selector, fn )
4963			fn = data;
4964			data = undefined;
4965		} else {
4966
4967			// ( types, data, fn )
4968			fn = data;
4969			data = selector;
4970			selector = undefined;
4971		}
4972	}
4973	if ( fn === false ) {
4974		fn = returnFalse;
4975	} else if ( !fn ) {
4976		return elem;
4977	}
4978
4979	if ( one === 1 ) {
4980		origFn = fn;
4981		fn = function( event ) {
4982
4983			// Can use an empty set, since event contains the info
4984			jQuery().off( event );
4985			return origFn.apply( this, arguments );
4986		};
4987
4988		// Use same guid so caller can remove using origFn
4989		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4990	}
4991	return elem.each( function() {
4992		jQuery.event.add( this, types, fn, data, selector );
4993	} );
4994}
4995
4996/*
4997 * Helper functions for managing events -- not part of the public interface.
4998 * Props to Dean Edwards' addEvent library for many of the ideas.
4999 */
5000jQuery.event = {
5001
5002	global: {},
5003
5004	add: function( elem, types, handler, data, selector ) {
5005
5006		var handleObjIn, eventHandle, tmp,
5007			events, t, handleObj,
5008			special, handlers, type, namespaces, origType,
5009			elemData = dataPriv.get( elem );
5010
5011		// Don't attach events to noData or text/comment nodes (but allow plain objects)
5012		if ( !elemData ) {
5013			return;
5014		}
5015
5016		// Caller can pass in an object of custom data in lieu of the handler
5017		if ( handler.handler ) {
5018			handleObjIn = handler;
5019			handler = handleObjIn.handler;
5020			selector = handleObjIn.selector;
5021		}
5022
5023		// Ensure that invalid selectors throw exceptions at attach time
5024		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
5025		if ( selector ) {
5026			jQuery.find.matchesSelector( documentElement, selector );
5027		}
5028
5029		// Make sure that the handler has a unique ID, used to find/remove it later
5030		if ( !handler.guid ) {
5031			handler.guid = jQuery.guid++;
5032		}
5033
5034		// Init the element's event structure and main handler, if this is the first
5035		if ( !( events = elemData.events ) ) {
5036			events = elemData.events = {};
5037		}
5038		if ( !( eventHandle = elemData.handle ) ) {
5039			eventHandle = elemData.handle = function( e ) {
5040
5041				// Discard the second event of a jQuery.event.trigger() and
5042				// when an event is called after a page has unloaded
5043				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
5044					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
5045			};
5046		}
5047
5048		// Handle multiple events separated by a space
5049		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5050		t = types.length;
5051		while ( t-- ) {
5052			tmp = rtypenamespace.exec( types[ t ] ) || [];
5053			type = origType = tmp[ 1 ];
5054			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5055
5056			// There *must* be a type, no attaching namespace-only handlers
5057			if ( !type ) {
5058				continue;
5059			}
5060
5061			// If event changes its type, use the special event handlers for the changed type
5062			special = jQuery.event.special[ type ] || {};
5063
5064			// If selector defined, determine special event api type, otherwise given type
5065			type = ( selector ? special.delegateType : special.bindType ) || type;
5066
5067			// Update special based on newly reset type
5068			special = jQuery.event.special[ type ] || {};
5069
5070			// handleObj is passed to all event handlers
5071			handleObj = jQuery.extend( {
5072				type: type,
5073				origType: origType,
5074				data: data,
5075				handler: handler,
5076				guid: handler.guid,
5077				selector: selector,
5078				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
5079				namespace: namespaces.join( "." )
5080			}, handleObjIn );
5081
5082			// Init the event handler queue if we're the first
5083			if ( !( handlers = events[ type ] ) ) {
5084				handlers = events[ type ] = [];
5085				handlers.delegateCount = 0;
5086
5087				// Only use addEventListener if the special events handler returns false
5088				if ( !special.setup ||
5089					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
5090
5091					if ( elem.addEventListener ) {
5092						elem.addEventListener( type, eventHandle );
5093					}
5094				}
5095			}
5096
5097			if ( special.add ) {
5098				special.add.call( elem, handleObj );
5099
5100				if ( !handleObj.handler.guid ) {
5101					handleObj.handler.guid = handler.guid;
5102				}
5103			}
5104
5105			// Add to the element's handler list, delegates in front
5106			if ( selector ) {
5107				handlers.splice( handlers.delegateCount++, 0, handleObj );
5108			} else {
5109				handlers.push( handleObj );
5110			}
5111
5112			// Keep track of which events have ever been used, for event optimization
5113			jQuery.event.global[ type ] = true;
5114		}
5115
5116	},
5117
5118	// Detach an event or set of events from an element
5119	remove: function( elem, types, handler, selector, mappedTypes ) {
5120
5121		var j, origCount, tmp,
5122			events, t, handleObj,
5123			special, handlers, type, namespaces, origType,
5124			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
5125
5126		if ( !elemData || !( events = elemData.events ) ) {
5127			return;
5128		}
5129
5130		// Once for each type.namespace in types; type may be omitted
5131		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5132		t = types.length;
5133		while ( t-- ) {
5134			tmp = rtypenamespace.exec( types[ t ] ) || [];
5135			type = origType = tmp[ 1 ];
5136			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5137
5138			// Unbind all events (on this namespace, if provided) for the element
5139			if ( !type ) {
5140				for ( type in events ) {
5141					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
5142				}
5143				continue;
5144			}
5145
5146			special = jQuery.event.special[ type ] || {};
5147			type = ( selector ? special.delegateType : special.bindType ) || type;
5148			handlers = events[ type ] || [];
5149			tmp = tmp[ 2 ] &&
5150				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
5151
5152			// Remove matching events
5153			origCount = j = handlers.length;
5154			while ( j-- ) {
5155				handleObj = handlers[ j ];
5156
5157				if ( ( mappedTypes || origType === handleObj.origType ) &&
5158					( !handler || handler.guid === handleObj.guid ) &&
5159					( !tmp || tmp.test( handleObj.namespace ) ) &&
5160					( !selector || selector === handleObj.selector ||
5161						selector === "**" && handleObj.selector ) ) {
5162					handlers.splice( j, 1 );
5163
5164					if ( handleObj.selector ) {
5165						handlers.delegateCount--;
5166					}
5167					if ( special.remove ) {
5168						special.remove.call( elem, handleObj );
5169					}
5170				}
5171			}
5172
5173			// Remove generic event handler if we removed something and no more handlers exist
5174			// (avoids potential for endless recursion during removal of special event handlers)
5175			if ( origCount && !handlers.length ) {
5176				if ( !special.teardown ||
5177					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5178
5179					jQuery.removeEvent( elem, type, elemData.handle );
5180				}
5181
5182				delete events[ type ];
5183			}
5184		}
5185
5186		// Remove data and the expando if it's no longer used
5187		if ( jQuery.isEmptyObject( events ) ) {
5188			dataPriv.remove( elem, "handle events" );
5189		}
5190	},
5191
5192	dispatch: function( nativeEvent ) {
5193
5194		// Make a writable jQuery.Event from the native event object
5195		var event = jQuery.event.fix( nativeEvent );
5196
5197		var i, j, ret, matched, handleObj, handlerQueue,
5198			args = new Array( arguments.length ),
5199			handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
5200			special = jQuery.event.special[ event.type ] || {};
5201
5202		// Use the fix-ed jQuery.Event rather than the (read-only) native event
5203		args[ 0 ] = event;
5204
5205		for ( i = 1; i < arguments.length; i++ ) {
5206			args[ i ] = arguments[ i ];
5207		}
5208
5209		event.delegateTarget = this;
5210
5211		// Call the preDispatch hook for the mapped type, and let it bail if desired
5212		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5213			return;
5214		}
5215
5216		// Determine handlers
5217		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5218
5219		// Run delegates first; they may want to stop propagation beneath us
5220		i = 0;
5221		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5222			event.currentTarget = matched.elem;
5223
5224			j = 0;
5225			while ( ( handleObj = matched.handlers[ j++ ] ) &&
5226				!event.isImmediatePropagationStopped() ) {
5227
5228				// If the event is namespaced, then each handler is only invoked if it is
5229				// specially universal or its namespaces are a superset of the event's.
5230				if ( !event.rnamespace || handleObj.namespace === false ||
5231					event.rnamespace.test( handleObj.namespace ) ) {
5232
5233					event.handleObj = handleObj;
5234					event.data = handleObj.data;
5235
5236					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5237						handleObj.handler ).apply( matched.elem, args );
5238
5239					if ( ret !== undefined ) {
5240						if ( ( event.result = ret ) === false ) {
5241							event.preventDefault();
5242							event.stopPropagation();
5243						}
5244					}
5245				}
5246			}
5247		}
5248
5249		// Call the postDispatch hook for the mapped type
5250		if ( special.postDispatch ) {
5251			special.postDispatch.call( this, event );
5252		}
5253
5254		return event.result;
5255	},
5256
5257	handlers: function( event, handlers ) {
5258		var i, handleObj, sel, matchedHandlers, matchedSelectors,
5259			handlerQueue = [],
5260			delegateCount = handlers.delegateCount,
5261			cur = event.target;
5262
5263		// Find delegate handlers
5264		if ( delegateCount &&
5265
vendor: 5,718 bytes, lines 5266-5451
5266			// Support: IE <=9
5267			// Black-hole SVG <use> instance trees (trac-13180)
5268			cur.nodeType &&
5269
5270			// Support: Firefox <=42
5271			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
5272			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
5273			// Support: IE 11 only
5274			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
5275			!( event.type === "click" && event.button >= 1 ) ) {
5276
5277			for ( ; cur !== this; cur = cur.parentNode || this ) {
5278
5279				// Don't check non-elements (#13208)
5280				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5281				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
5282					matchedHandlers = [];
5283					matchedSelectors = {};
5284					for ( i = 0; i < delegateCount; i++ ) {
5285						handleObj = handlers[ i ];
5286
5287						// Don't conflict with Object.prototype properties (#13203)
5288						sel = handleObj.selector + " ";
5289
5290						if ( matchedSelectors[ sel ] === undefined ) {
5291							matchedSelectors[ sel ] = handleObj.needsContext ?
5292								jQuery( sel, this ).index( cur ) > -1 :
5293								jQuery.find( sel, this, null, [ cur ] ).length;
5294						}
5295						if ( matchedSelectors[ sel ] ) {
5296							matchedHandlers.push( handleObj );
5297						}
5298					}
5299					if ( matchedHandlers.length ) {
5300						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
5301					}
5302				}
5303			}
5304		}
5305
5306		// Add the remaining (directly-bound) handlers
5307		cur = this;
5308		if ( delegateCount < handlers.length ) {
5309			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
5310		}
5311
5312		return handlerQueue;
5313	},
5314
5315	addProp: function( name, hook ) {
5316		Object.defineProperty( jQuery.Event.prototype, name, {
5317			enumerable: true,
5318			configurable: true,
5319
5320			get: isFunction( hook ) ?
5321				function() {
5322					if ( this.originalEvent ) {
5323							return hook( this.originalEvent );
5324					}
5325				} :
5326				function() {
5327					if ( this.originalEvent ) {
5328							return this.originalEvent[ name ];
5329					}
5330				},
5331
5332			set: function( value ) {
5333				Object.defineProperty( this, name, {
5334					enumerable: true,
5335					configurable: true,
5336					writable: true,
5337					value: value
5338				} );
5339			}
5340		} );
5341	},
5342
5343	fix: function( originalEvent ) {
5344		return originalEvent[ jQuery.expando ] ?
5345			originalEvent :
5346			new jQuery.Event( originalEvent );
5347	},
5348
5349	special: {
5350		load: {
5351
5352			// Prevent triggered image.load events from bubbling to window.load
5353			noBubble: true
5354		},
5355		click: {
5356
5357			// Utilize native event to ensure correct state for checkable inputs
5358			setup: function( data ) {
5359
5360				// For mutual compressibility with _default, replace `this` access with a local var.
5361				// `|| data` is dead code meant only to preserve the variable through minification.
5362				var el = this || data;
5363
5364				// Claim the first handler
5365				if ( rcheckableType.test( el.type ) &&
5366					el.click && nodeName( el, "input" ) ) {
5367
5368					// dataPriv.set( el, "click", ... )
5369					leverageNative( el, "click", returnTrue );
5370				}
5371
5372				// Return false to allow normal processing in the caller
5373				return false;
5374			},
5375			trigger: function( data ) {
5376
5377				// For mutual compressibility with _default, replace `this` access with a local var.
5378				// `|| data` is dead code meant only to preserve the variable through minification.
5379				var el = this || data;
5380
5381				// Force setup before triggering a click
5382				if ( rcheckableType.test( el.type ) &&
5383					el.click && nodeName( el, "input" ) ) {
5384
5385					leverageNative( el, "click" );
5386				}
5387
5388				// Return non-false to allow normal event-path propagation
5389				return true;
5390			},
5391
5392			// For cross-browser consistency, suppress native .click() on links
5393			// Also prevent it if we're currently inside a leveraged native-event stack
5394			_default: function( event ) {
5395				var target = event.target;
5396				return rcheckableType.test( target.type ) &&
5397					target.click && nodeName( target, "input" ) &&
5398					dataPriv.get( target, "click" ) ||
5399					nodeName( target, "a" );
5400			}
5401		},
5402
5403		beforeunload: {
5404			postDispatch: function( event ) {
5405
5406				// Support: Firefox 20+
5407				// Firefox doesn't alert if the returnValue field is not set.
5408				if ( event.result !== undefined && event.originalEvent ) {
5409					event.originalEvent.returnValue = event.result;
5410				}
5411			}
5412		}
5413	}
5414};
5415
5416// Ensure the presence of an event listener that handles manually-triggered
5417// synthetic events by interrupting progress until reinvoked in response to
5418// *native* events that it fires directly, ensuring that state changes have
5419// already occurred before other listeners are invoked.
5420function leverageNative( el, type, expectSync ) {
5421
5422	// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
5423	if ( !expectSync ) {
5424		if ( dataPriv.get( el, type ) === undefined ) {
5425			jQuery.event.add( el, type, returnTrue );
5426		}
5427		return;
5428	}
5429
5430	// Register the controller as a special universal handler for all event namespaces
5431	dataPriv.set( el, type, false );
5432	jQuery.event.add( el, type, {
5433		namespace: false,
5434		handler: function( event ) {
5435			var notAsync, result,
5436				saved = dataPriv.get( this, type );
5437
5438			if ( ( event.isTrigger & 1 ) && this[ type ] ) {
5439
5440				// Interrupt processing of the outer synthetic .trigger()ed event
5441				// Saved data should be false in such cases, but might be a leftover capture object
5442				// from an async native handler (gh-4350)
5443				if ( !saved.length ) {
5444
5445					// Store arguments for use when handling the inner native event
5446					// There will always be at least one argument (an event object), so this array
5447					// will not be confused with a leftover capture object.
5448					saved = slice.call( arguments );
5449					dataPriv.set( this, type, saved );
5450
5451					// Trigger the native event and capture its result
5452					// Support: IE <=9 - 11+
5453					// focus() and blur() are asynchronous
5454					notAsync = expectSync( this, type );
5455					this[ type ]();
5456					result = dataPriv.get( this, type );
5457					if ( saved !== result || notAsync ) {
5458						dataPriv.set( this, type, false );
5459					} else {
5460						result = {};
5461					}
5462					if ( saved !== result ) {
5463
5464						// Cancel the outer synthetic event
5465						event.stopImmediatePropagation();
5466						event.preventDefault();
5467						return result.value;
5468					}
5469
5470				// If this is an inner synthetic event for an event with a bubbling surrogate
5471				// (focus or blur), assume that the surrogate already propagated from triggering the
5472				// native event and prevent that from happening again here.
5473				// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
5474				// bubbling surrogate propagates *after* the non-bubbling base), but that seems
5475				// less bad than duplication.
5476				} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
5477					event.stopPropagation();
5478				}
5479
5480			// If this is a native event triggered above, everything is now in order
5481			// Fire an inner synthetic event with the original arguments
5482			} else if ( saved.length ) {
5483
5484				// ...and capture the result
5485				dataPriv.set( this, type, {
5486					value: jQuery.event.trigger(
5487
5488						// Support: IE <=9 - 11+
5489						// Extend with the prototype to reset the above stopImmediatePropagation()
5490						jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
5491						saved.slice( 1 ),
5492						this
5493					)
5494				} );
5495
5496				// Abort handling of the native event
5497				event.stopImmediatePropagation();
5498			}
5499		}
5500	} );
5501}
5502
5503jQuery.removeEvent = function( elem, type, handle ) {
5504
5505	// This "if" is needed for plain objects
5506	if ( elem.removeEventListener ) {
5507		elem.removeEventListener( type, handle );
5508	}
5509};
5510
5511jQuery.Event = function( src, props ) {
5512
5513	// Allow instantiation without the 'new' keyword
5514	if ( !( this instanceof jQuery.Event ) ) {
5515		return new jQuery.Event( src, props );
5516	}
5517
5518	// Event object
5519	if ( src && src.type ) {
5520		this.originalEvent = src;
5521		this.type = src.type;
5522
5523		// Events bubbling up the document may have been marked as prevented
5524		// by a handler lower down the tree; reflect the correct value.
5525		this.isDefaultPrevented = src.defaultPrevented ||
5526				src.defaultPrevented === undefined &&
5527
5528				// Support: Android <=2.3 only
5529				src.returnValue === false ?
5530			returnTrue :
5531			returnFalse;
5532
5533		// Create target properties
5534		// Support: Safari <=6 - 7 only
5535		// Target should not be a text node (#504, #13143)
5536		this.target = ( src.target && src.target.nodeType === 3 ) ?
5537			src.target.parentNode :
5538			src.target;
5539
5540		this.currentTarget = src.currentTarget;
5541		this.relatedTarget = src.relatedTarget;
5542
5543	// Event type
5544	} else {
5545		this.type = src;
5546	}
5547
5548	// Put explicitly provided properties onto the event object
5549	if ( props ) {
5550		jQuery.extend( this, props );
5551	}
5552
5553	// Create a timestamp if incoming event doesn't have one
5554	this.timeStamp = src && src.timeStamp || Date.now();
5555
5556	// Mark it as fixed
5557	this[ jQuery.expando ] = true;
5558};
5559
5560// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5561// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5562jQuery.Event.prototype = {
5563	constructor: jQuery.Event,
5564	isDefaultPrevented: returnFalse,
5565	isPropagationStopped: returnFalse,
5566	isImmediatePropagationStopped: returnFalse,
5567	isSimulated: false,
5568
5569	preventDefault: function() {
5570		var e = this.originalEvent;
5571
5572		this.isDefaultPrevented = returnTrue;
5573
5574		if ( e && !this.isSimulated ) {
5575			e.preventDefault();
5576		}
5577	},
5578	stopPropagation: function() {
5579		var e = this.originalEvent;
5580
5581		this.isPropagationStopped = returnTrue;
5582
5583		if ( e && !this.isSimulated ) {
5584			e.stopPropagation();
5585		}
5586	},
5587	stopImmediatePropagation: function() {
5588		var e = this.originalEvent;
5589
5590		this.isImmediatePropagationStopped = returnTrue;
5591
5592		if ( e && !this.isSimulated ) {
5593			e.stopImmediatePropagation();
5594		}
5595
5596		this.stopPropagation();
5597	}
5598};
5599
5600// Includes all common event props including KeyEvent and MouseEvent specific props
5601jQuery.each( {
5602	altKey: true,
5603	bubbles: true,
5604	cancelable: true,
5605	changedTouches: true,
5606	ctrlKey: true,
5607	detail: true,
5608	eventPhase: true,
5609	metaKey: true,
5610	pageX: true,
5611	pageY: true,
5612	shiftKey: true,
5613	view: true,
5614	"char": true,
5615	code: true,
5616	charCode: true,
5617	key: true,
5618	keyCode: true,
5619	button: true,
5620	buttons: true,
5621	clientX: true,
5622	clientY: true,
5623	offsetX: true,
5624	offsetY: true,
5625	pointerId: true,
5626	pointerType: true,
5627	screenX: true,
5628	screenY: true,
5629	targetTouches: true,
5630	toElement: true,
5631	touches: true,
5632
5633	which: function( event ) {
5634		var button = event.button;
5635
5636		// Add which for key events
5637		if ( event.which == null && rkeyEvent.test( event.type ) ) {
5638			return event.charCode != null ? event.charCode : event.keyCode;
5639		}
5640
5641		// Add which for click: 1 === left; 2 === middle; 3 === right
5642		if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
5643			if ( button & 1 ) {
5644				return 1;
5645			}
5646
5647			if ( button & 2 ) {
5648				return 3;
5649			}
5650
5651			if ( button & 4 ) {
5652				return 2;
5653			}
5654
5655			return 0;
5656		}
5657
5658		return event.which;
5659	}
5660}, jQuery.event.addProp );
5661
5662jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
5663	jQuery.event.special[ type ] = {
5664
5665		// Utilize native event if possible so blur/focus sequence is correct
5666		setup: function() {
5667
5668			// Claim the first handler
5669			// dataPriv.set( this, "focus", ... )
5670			// dataPriv.set( this, "blur", ... )
5671			leverageNative( this, type, expectSync );
5672
5673			// Return false to allow normal processing in the caller
5674			return false;
vendor: 8,337 bytes, lines 5675-5985
5675		},
5676		trigger: function() {
5677
5678			// Force setup before trigger
5679			leverageNative( this, type );
5680
5681			// Return non-false to allow normal event-path propagation
5682			return true;
5683		},
5684
5685		delegateType: delegateType
5686	};
5687} );
5688
5689// Create mouseenter/leave events using mouseover/out and event-time checks
5690// so that event delegation works in jQuery.
5691// Do the same for pointerenter/pointerleave and pointerover/pointerout
5692//
5693// Support: Safari 7 only
5694// Safari sends mouseenter too often; see:
5695// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
5696// for the description of the bug (it existed in older Chrome versions as well).
5697jQuery.each( {
5698	mouseenter: "mouseover",
5699	mouseleave: "mouseout",
5700	pointerenter: "pointerover",
5701	pointerleave: "pointerout"
5702}, function( orig, fix ) {
5703	jQuery.event.special[ orig ] = {
5704		delegateType: fix,
5705		bindType: fix,
5706
5707		handle: function( event ) {
5708			var ret,
5709				target = this,
5710				related = event.relatedTarget,
5711				handleObj = event.handleObj;
5712
5713			// For mouseenter/leave call the handler if related is outside the target.
5714			// NB: No relatedTarget if the mouse left/entered the browser window
5715			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5716				event.type = handleObj.origType;
5717				ret = handleObj.handler.apply( this, arguments );
5718				event.type = fix;
5719			}
5720			return ret;
5721		}
5722	};
5723} );
5724
5725jQuery.fn.extend( {
5726
5727	on: function( types, selector, data, fn ) {
5728		return on( this, types, selector, data, fn );
5729	},
5730	one: function( types, selector, data, fn ) {
5731		return on( this, types, selector, data, fn, 1 );
5732	},
5733	off: function( types, selector, fn ) {
5734		var handleObj, type;
5735		if ( types && types.preventDefault && types.handleObj ) {
5736
5737			// ( event )  dispatched jQuery.Event
5738			handleObj = types.handleObj;
5739			jQuery( types.delegateTarget ).off(
5740				handleObj.namespace ?
5741					handleObj.origType + "." + handleObj.namespace :
5742					handleObj.origType,
5743				handleObj.selector,
5744				handleObj.handler
5745			);
5746			return this;
5747		}
5748		if ( typeof types === "object" ) {
5749
5750			// ( types-object [, selector] )
5751			for ( type in types ) {
5752				this.off( type, selector, types[ type ] );
5753			}
5754			return this;
5755		}
5756		if ( selector === false || typeof selector === "function" ) {
5757
5758			// ( types [, fn] )
5759			fn = selector;
5760			selector = undefined;
5761		}
5762		if ( fn === false ) {
5763			fn = returnFalse;
5764		}
5765		return this.each( function() {
5766			jQuery.event.remove( this, types, fn, selector );
5767		} );
5768	}
5769} );
5770
5771
5772var
5773
5774	/* eslint-disable max-len */
5775
5776	// See https://github.com/eslint/eslint/issues/3229
5777	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
5778
5779	/* eslint-enable */
5780
5781	// Support: IE <=10 - 11, Edge 12 - 13 only
5782	// In IE/Edge using regex groups here causes severe slowdowns.
5783	// See https://connect.microsoft.com/IE/feedback/details/1736512/
5784	rnoInnerhtml = /<script|<style|<link/i,
5785
5786	// checked="checked" or checked
5787	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5788	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
5789
5790// Prefer a tbody over its parent table for containing new rows
5791function manipulationTarget( elem, content ) {
5792	if ( nodeName( elem, "table" ) &&
5793		nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
5794
5795		return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
5796	}
5797
5798	return elem;
5799}
5800
5801// Replace/restore the type attribute of script elements for safe DOM manipulation
5802function disableScript( elem ) {
5803	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
5804	return elem;
5805}
5806function restoreScript( elem ) {
5807	if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
5808		elem.type = elem.type.slice( 5 );
5809	} else {
5810		elem.removeAttribute( "type" );
5811	}
5812
5813	return elem;
5814}
5815
5816function cloneCopyEvent( src, dest ) {
5817	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
5818
5819	if ( dest.nodeType !== 1 ) {
5820		return;
5821	}
5822
5823	// 1. Copy private data: events, handlers, etc.
5824	if ( dataPriv.hasData( src ) ) {
5825		pdataOld = dataPriv.access( src );
5826		pdataCur = dataPriv.set( dest, pdataOld );
5827		events = pdataOld.events;
5828
5829		if ( events ) {
5830			delete pdataCur.handle;
5831			pdataCur.events = {};
5832
5833			for ( type in events ) {
5834				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5835					jQuery.event.add( dest, type, events[ type ][ i ] );
5836				}
5837			}
5838		}
5839	}
5840
5841	// 2. Copy user data
5842	if ( dataUser.hasData( src ) ) {
5843		udataOld = dataUser.access( src );
5844		udataCur = jQuery.extend( {}, udataOld );
5845
5846		dataUser.set( dest, udataCur );
5847	}
5848}
5849
5850// Fix IE bugs, see support tests
5851function fixInput( src, dest ) {
5852	var nodeName = dest.nodeName.toLowerCase();
5853
5854	// Fails to persist the checked state of a cloned checkbox or radio button.
5855	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5856		dest.checked = src.checked;
5857
5858	// Fails to return the selected option to the default selected state when cloning options
5859	} else if ( nodeName === "input" || nodeName === "textarea" ) {
5860		dest.defaultValue = src.defaultValue;
5861	}
5862}
5863
5864function domManip( collection, args, callback, ignored ) {
5865
5866	// Flatten any nested arrays
5867	args = concat.apply( [], args );
5868
5869	var fragment, first, scripts, hasScripts, node, doc,
5870		i = 0,
5871		l = collection.length,
5872		iNoClone = l - 1,
5873		value = args[ 0 ],
5874		valueIsFunction = isFunction( value );
5875
5876	// We can't cloneNode fragments that contain checked, in WebKit
5877	if ( valueIsFunction ||
5878			( l > 1 && typeof value === "string" &&
5879				!support.checkClone && rchecked.test( value ) ) ) {
5880		return collection.each( function( index ) {
5881			var self = collection.eq( index );
5882			if ( valueIsFunction ) {
5883				args[ 0 ] = value.call( this, index, self.html() );
5884			}
5885			domManip( self, args, callback, ignored );
5886		} );
5887	}
5888
5889	if ( l ) {
5890		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
5891		first = fragment.firstChild;
5892
5893		if ( fragment.childNodes.length === 1 ) {
5894			fragment = first;
5895		}
5896
5897		// Require either new content or an interest in ignored elements to invoke the callback
5898		if ( first || ignored ) {
5899			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5900			hasScripts = scripts.length;
5901
5902			// Use the original fragment for the last item
5903			// instead of the first because it can end up
5904			// being emptied incorrectly in certain situations (#8070).
5905			for ( ; i < l; i++ ) {
5906				node = fragment;
5907
5908				if ( i !== iNoClone ) {
5909					node = jQuery.clone( node, true, true );
5910
5911					// Keep references to cloned scripts for later restoration
5912					if ( hasScripts ) {
5913
5914						// Support: Android <=4.0 only, PhantomJS 1 only
5915						// push.apply(_, arraylike) throws on ancient WebKit
5916						jQuery.merge( scripts, getAll( node, "script" ) );
5917					}
5918				}
5919
5920				callback.call( collection[ i ], node, i );
5921			}
5922
5923			if ( hasScripts ) {
5924				doc = scripts[ scripts.length - 1 ].ownerDocument;
5925
5926				// Reenable scripts
5927				jQuery.map( scripts, restoreScript );
5928
5929				// Evaluate executable scripts on first document insertion
5930				for ( i = 0; i < hasScripts; i++ ) {
5931					node = scripts[ i ];
5932					if ( rscriptType.test( node.type || "" ) &&
5933						!dataPriv.access( node, "globalEval" ) &&
5934						jQuery.contains( doc, node ) ) {
5935
5936						if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {
5937
5938							// Optional AJAX dependency, but won't run scripts if not present
5939							if ( jQuery._evalUrl && !node.noModule ) {
5940								jQuery._evalUrl( node.src, {
5941									nonce: node.nonce || node.getAttribute( "nonce" )
5942								} );
5943							}
5944						} else {
5945							DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
5946						}
5947					}
5948				}
5949			}
5950		}
5951	}
5952
5953	return collection;
5954}
5955
5956function remove( elem, selector, keepData ) {
5957	var node,
5958		nodes = selector ? jQuery.filter( selector, elem ) : elem,
5959		i = 0;
5960
5961	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
5962		if ( !keepData && node.nodeType === 1 ) {
5963			jQuery.cleanData( getAll( node ) );
5964		}
5965
5966		if ( node.parentNode ) {
5967			if ( keepData && isAttached( node ) ) {
5968				setGlobalEval( getAll( node, "script" ) );
5969			}
5970			node.parentNode.removeChild( node );
5971		}
5972	}
5973
5974	return elem;
5975}
5976
5977jQuery.extend( {
5978	htmlPrefilter: function( html ) {
5979		return html.replace( rxhtmlTag, "<$1></$2>" );
5980	},
5981
5982	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5983		var i, l, srcElements, destElements,
5984			clone = elem.cloneNode( true ),
5985			inPage = isAttached(
vendor: 5,988 bytes, lines 5985-6225
5985 elem );
5986
5987		// Fix IE cloning issues
5988		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5989				!jQuery.isXMLDoc( elem ) ) {
5990
5991			// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
5992			destElements = getAll( clone );
5993			srcElements = getAll( elem );
5994
5995			for ( i = 0, l = srcElements.length; i < l; i++ ) {
5996				fixInput( srcElements[ i ], destElements[ i ] );
5997			}
5998		}
5999
6000		// Copy the events from the original to the clone
6001		if ( dataAndEvents ) {
6002			if ( deepDataAndEvents ) {
6003				srcElements = srcElements || getAll( elem );
6004				destElements = destElements || getAll( clone );
6005
6006				for ( i = 0, l = srcElements.length; i < l; i++ ) {
6007					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
6008				}
6009			} else {
6010				cloneCopyEvent( elem, clone );
6011			}
6012		}
6013
6014		// Preserve script evaluation history
6015		destElements = getAll( clone, "script" );
6016		if ( destElements.length > 0 ) {
6017			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6018		}
6019
6020		// Return the cloned set
6021		return clone;
6022	},
6023
6024	cleanData: function( elems ) {
6025		var data, elem, type,
6026			special = jQuery.event.special,
6027			i = 0;
6028
6029		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
6030			if ( acceptData( elem ) ) {
6031				if ( ( data = elem[ dataPriv.expando ] ) ) {
6032					if ( data.events ) {
6033						for ( type in data.events ) {
6034							if ( special[ type ] ) {
6035								jQuery.event.remove( elem, type );
6036
6037							// This is a shortcut to avoid jQuery.event.remove's overhead
6038							} else {
6039								jQuery.removeEvent( elem, type, data.handle );
6040							}
6041						}
6042					}
6043
6044					// Support: Chrome <=35 - 45+
6045					// Assign undefined instead of using delete, see Data#remove
6046					elem[ dataPriv.expando ] = undefined;
6047				}
6048				if ( elem[ dataUser.expando ] ) {
6049
6050					// Support: Chrome <=35 - 45+
6051					// Assign undefined instead of using delete, see Data#remove
6052					elem[ dataUser.expando ] = undefined;
6053				}
6054			}
6055		}
6056	}
6057} );
6058
6059jQuery.fn.extend( {
6060	detach: function( selector ) {
6061		return remove( this, selector, true );
6062	},
6063
6064	remove: function( selector ) {
6065		return remove( this, selector );
6066	},
6067
6068	text: function( value ) {
6069		return access( this, function( value ) {
6070			return value === undefined ?
6071				jQuery.text( this ) :
6072				this.empty().each( function() {
6073					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6074						this.textContent = value;
6075					}
6076				} );
6077		}, null, value, arguments.length );
6078	},
6079
6080	append: function() {
6081		return domManip( this, arguments, function( elem ) {
6082			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6083				var target = manipulationTarget( this, elem );
6084				target.appendChild( elem );
6085			}
6086		} );
6087	},
6088
6089	prepend: function() {
6090		return domManip( this, arguments, function( elem ) {
6091			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6092				var target = manipulationTarget( this, elem );
6093				target.insertBefore( elem, target.firstChild );
6094			}
6095		} );
6096	},
6097
6098	before: function() {
6099		return domManip( this, arguments, function( elem ) {
6100			if ( this.parentNode ) {
6101				this.parentNode.insertBefore( elem, this );
6102			}
6103		} );
6104	},
6105
6106	after: function() {
6107		return domManip( this, arguments, function( elem ) {
6108			if ( this.parentNode ) {
6109				this.parentNode.insertBefore( elem, this.nextSibling );
6110			}
6111		} );
6112	},
6113
6114	empty: function() {
6115		var elem,
6116			i = 0;
6117
6118		for ( ; ( elem = this[ i ] ) != null; i++ ) {
6119			if ( elem.nodeType === 1 ) {
6120
6121				// Prevent memory leaks
6122				jQuery.cleanData( getAll( elem, false ) );
6123
6124				// Remove any remaining nodes
6125				elem.textContent = "";
6126			}
6127		}
6128
6129		return this;
6130	},
6131
6132	clone: function( dataAndEvents, deepDataAndEvents ) {
6133		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6134		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6135
6136		return this.map( function() {
6137			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6138		} );
6139	},
6140
6141	html: function( value ) {
6142		return access( this, function( value ) {
6143			var elem = this[ 0 ] || {},
6144				i = 0,
6145				l = this.length;
6146
6147			if ( value === undefined && elem.nodeType === 1 ) {
6148				return elem.innerHTML;
6149			}
6150
6151			// See if we can take a shortcut and just use innerHTML
6152			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6153				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
6154
6155				value = jQuery.htmlPrefilter( value );
6156
6157				try {
6158					for ( ; i < l; i++ ) {
6159						elem = this[ i ] || {};
6160
6161						// Remove element nodes and prevent memory leaks
6162						if ( elem.nodeType === 1 ) {
6163							jQuery.cleanData( getAll( elem, false ) );
6164							elem.innerHTML = value;
6165						}
6166					}
6167
6168					elem = 0;
6169
6170				// If using innerHTML throws an exception, use the fallback method
6171				} catch ( e ) {}
6172			}
6173
6174			if ( elem ) {
6175				this.empty().append( value );
6176			}
6177		}, null, value, arguments.length );
6178	},
6179
6180	replaceWith: function() {
6181		var ignored = [];
6182
6183		// Make the changes, replacing each non-ignored context element with the new content
6184		return domManip( this, arguments, function( elem ) {
6185			var parent = this.parentNode;
6186
6187			if ( jQuery.inArray( this, ignored ) < 0 ) {
6188				jQuery.cleanData( getAll( this ) );
6189				if ( parent ) {
6190					parent.replaceChild( elem, this );
6191				}
6192			}
6193
6194		// Force callback invocation
6195		}, ignored );
6196	}
6197} );
6198
6199jQuery.each( {
6200	appendTo: "append",
6201	prependTo: "prepend",
6202	insertBefore: "before",
6203	insertAfter: "after",
6204	replaceAll: "replaceWith"
6205}, function( name, original ) {
6206	jQuery.fn[ name ] = function( selector ) {
6207		var elems,
6208			ret = [],
6209			insert = jQuery( selector ),
6210			last = insert.length - 1,
6211			i = 0;
6212
6213		for ( ; i <= last; i++ ) {
6214			elems = i === last ? this : this.clone( true );
6215			jQuery( insert[ i ] )[ original ]( elems );
6216
6217			// Support: Android <=4.0 only, PhantomJS 1 only
6218			// .get() because push.apply(_, arraylike) throws on ancient WebKit
6219			push.apply( ret, elems.get() );
6220		}
6221
6222		return this.pushStack( ret );
6223	};
6224} );
6225var r
6225numnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6226
6227var getStyles = function( elem ) {
6228
6229		// Support: IE <=11 only, Firefox <=30 (#15098, #14150)
6230		// IE throws on elements created in popups
6231		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6232		var view = elem.ownerDocument.defaultView;
6233
6234		if ( !view || !view.opener ) {
6235			view = window;
6236		}
6237
6238		return view.getComputedStyle( elem );
6239	};
6240
6241var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6242
6243
6244
6245( function() {
6246
6247	// Executing both pixelPosition & boxSizingReliable tests require only one layout
6248	// so they're executed at the same time to save the second computation.
6249	function computeStyleTests() {
6250
6251		// This is a singleton, we need to execute it only once
6252		if ( !div ) {
6253			return;
6254		}
6255
6256		container.style.cssText = "position:absolute;
vendor: 24,862 bytes, lines 6256-7147
6256left:-11111px;width:60px;" +
6257			"margin-top:1px;padding:0;border:0";
6258		div.style.cssText =
6259			"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
6260			"margin:auto;border:1px;padding:1px;" +
6261			"width:60%;top:1%";
6262		documentElement.appendChild( container ).appendChild( div );
6263
6264		var divStyle = window.getComputedStyle( div );
6265		pixelPositionVal = divStyle.top !== "1%";
6266
6267		// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
6268		reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
6269
6270		// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
6271		// Some styles come back with percentage values, even though they shouldn't
6272		div.style.right = "60%";
6273		pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
6274
6275		// Support: IE 9 - 11 only
6276		// Detect misreporting of content dimensions for box-sizing:border-box elements
6277		boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
6278
6279		// Support: IE 9 only
6280		// Detect overflow:scroll screwiness (gh-3699)
6281		// Support: Chrome <=64
6282		// Don't get tricked when zoom affects offsetWidth (gh-4029)
6283		div.style.position = "absolute";
6284		scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
6285
6286		documentElement.removeChild( container );
6287
6288		// Nullify the div so it wouldn't be stored in the memory and
6289		// it will also be a sign that checks already performed
6290		div = null;
6291	}
6292
6293	function roundPixelMeasures( measure ) {
6294		return Math.round( parseFloat( measure ) );
6295	}
6296
6297	var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
6298		reliableMarginLeftVal,
6299		container = document.createElement( "div" ),
6300		div = document.createElement( "div" );
6301
6302	// Finish early in limited (non-browser) environments
6303	if ( !div.style ) {
6304		return;
6305	}
6306
6307	// Support: IE <=9 - 11 only
6308	// Style of cloned element affects source element cloned (#8908)
6309	div.style.backgroundClip = "content-box";
6310	div.cloneNode( true ).style.backgroundClip = "";
6311	support.clearCloneStyle = div.style.backgroundClip === "content-box";
6312
6313	jQuery.extend( support, {
6314		boxSizingReliable: function() {
6315			computeStyleTests();
6316			return boxSizingReliableVal;
6317		},
6318		pixelBoxStyles: function() {
6319			computeStyleTests();
6320			return pixelBoxStylesVal;
6321		},
6322		pixelPosition: function() {
6323			computeStyleTests();
6324			return pixelPositionVal;
6325		},
6326		reliableMarginLeft: function() {
6327			computeStyleTests();
6328			return reliableMarginLeftVal;
6329		},
6330		scrollboxSize: function() {
6331			computeStyleTests();
6332			return scrollboxSizeVal;
6333		}
6334	} );
6335} )();
6336
6337
6338function curCSS( elem, name, computed ) {
6339	var width, minWidth, maxWidth, ret,
6340
6341		// Support: Firefox 51+
6342		// Retrieving style before computed somehow
6343		// fixes an issue with getting wrong values
6344		// on detached elements
6345		style = elem.style;
6346
6347	computed = computed || getStyles( elem );
6348
6349	// getPropertyValue is needed for:
6350	//   .css('filter') (IE 9 only, #12537)
6351	//   .css('--customProperty) (#3144)
6352	if ( computed ) {
6353		ret = computed.getPropertyValue( name ) || computed[ name ];
6354
6355		if ( ret === "" && !isAttached( elem ) ) {
6356			ret = jQuery.style( elem, name );
6357		}
6358
6359		// A tribute to the "awesome hack by Dean Edwards"
6360		// Android Browser returns percentage for some values,
6361		// but width seems to be reliably pixels.
6362		// This is against the CSSOM draft spec:
6363		// https://drafts.csswg.org/cssom/#resolved-values
6364		if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
6365
6366			// Remember the original values
6367			width = style.width;
6368			minWidth = style.minWidth;
6369			maxWidth = style.maxWidth;
6370
6371			// Put in the new values to get a computed value out
6372			style.minWidth = style.maxWidth = style.width = ret;
6373			ret = computed.width;
6374
6375			// Revert the changed values
6376			style.width = width;
6377			style.minWidth = minWidth;
6378			style.maxWidth = maxWidth;
6379		}
6380	}
6381
6382	return ret !== undefined ?
6383
6384		// Support: IE <=9 - 11 only
6385		// IE returns zIndex value as an integer.
6386		ret + "" :
6387		ret;
6388}
6389
6390
6391function addGetHookIf( conditionFn, hookFn ) {
6392
6393	// Define the hook, we'll check on the first run if it's really needed.
6394	return {
6395		get: function() {
6396			if ( conditionFn() ) {
6397
6398				// Hook not needed (or it's not possible to use it due
6399				// to missing dependency), remove it.
6400				delete this.get;
6401				return;
6402			}
6403
6404			// Hook needed; redefine it so that the support test is not executed again.
6405			return ( this.get = hookFn ).apply( this, arguments );
6406		}
6407	};
6408}
6409
6410
6411var cssPrefixes = [ "Webkit", "Moz", "ms" ],
6412	emptyStyle = document.createElement( "div" ).style,
6413	vendorProps = {};
6414
6415// Return a vendor-prefixed property or undefined
6416function vendorPropName( name ) {
6417
6418	// Check for vendor prefixed names
6419	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
6420		i = cssPrefixes.length;
6421
6422	while ( i-- ) {
6423		name = cssPrefixes[ i ] + capName;
6424		if ( name in emptyStyle ) {
6425			return name;
6426		}
6427	}
6428}
6429
6430// Return a potentially-mapped jQuery.cssProps or vendor prefixed property
6431function finalPropName( name ) {
6432	var final = jQuery.cssProps[ name ] || vendorProps[ name ];
6433
6434	if ( final ) {
6435		return final;
6436	}
6437	if ( name in emptyStyle ) {
6438		return name;
6439	}
6440	return vendorProps[ name ] = vendorPropName( name ) || name;
6441}
6442
6443
6444var
6445
6446	// Swappable if display is none or starts with table
6447	// except "table", "table-cell", or "table-caption"
6448	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6449	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6450	rcustomProp = /^--/,
6451	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6452	cssNormalTransform = {
6453		letterSpacing: "0",
6454		fontWeight: "400"
6455	};
6456
6457function setPositiveNumber( elem, value, subtract ) {
6458
6459	// Any relative (+/-) values have already been
6460	// normalized at this point
6461	var matches = rcssNum.exec( value );
6462	return matches ?
6463
6464		// Guard against undefined "subtract", e.g., when used as in cssHooks
6465		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
6466		value;
6467}
6468
6469function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
6470	var i = dimension === "width" ? 1 : 0,
6471		extra = 0,
6472		delta = 0;
6473
6474	// Adjustment may not be necessary
6475	if ( box === ( isBorderBox ? "border" : "content" ) ) {
6476		return 0;
6477	}
6478
6479	for ( ; i < 4; i += 2 ) {
6480
6481		// Both box models exclude margin
6482		if ( box === "margin" ) {
6483			delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
6484		}
6485
6486		// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
6487		if ( !isBorderBox ) {
6488
6489			// Add padding
6490			delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6491
6492			// For "border" or "margin", add border
6493			if ( box !== "padding" ) {
6494				delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6495
6496			// But still keep track of it otherwise
6497			} else {
6498				extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6499			}
6500
6501		// If we get here with a border-box (content + padding + border), we're seeking "content" or
6502		// "padding" or "margin"
6503		} else {
6504
6505			// For "content", subtract padding
6506			if ( box === "content" ) {
6507				delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6508			}
6509
6510			// For "content" or "padding", subtract border
6511			if ( box !== "margin" ) {
6512				delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6513			}
6514		}
6515	}
6516
6517	// Account for positive content-box scroll gutter when requested by providing computedVal
6518	if ( !isBorderBox && computedVal >= 0 ) {
6519
6520		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
6521		// Assuming integer scroll gutter, subtract the rest and round down
6522		delta += Math.max( 0, Math.ceil(
6523			elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6524			computedVal -
6525			delta -
6526			extra -
6527			0.5
6528
6529		// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
6530		// Use an explicit zero to avoid NaN (gh-3964)
6531		) ) || 0;
6532	}
6533
6534	return delta;
6535}
6536
6537function getWidthOrHeight( elem, dimension, extra ) {
6538
6539	// Start with computed style
6540	var styles = getStyles( elem ),
6541
6542		// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
6543		// Fake content-box until we know it's needed to know the true value.
6544		boxSizingNeeded = !support.boxSizingReliable() || extra,
6545		isBorderBox = boxSizingNeeded &&
6546			jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6547		valueIsBorderBox = isBorderBox,
6548
6549		val = curCSS( elem, dimension, styles ),
6550		offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
6551
6552	// Support: Firefox <=54
6553	// Return a confounding non-pixel value or feign ignorance, as appropriate.
6554	if ( rnumnonpx.test( val ) ) {
6555		if ( !extra ) {
6556			return val;
6557		}
6558		val = "auto";
6559	}
6560
6561
6562	// Fall back to offsetWidth/offsetHeight when value is "auto"
6563	// This happens for inline elements with no explicit setting (gh-3571)
6564	// Support: Android <=4.1 - 4.3 only
6565	// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
6566	// Support: IE 9-11 only
6567	// Also use offsetWidth/offsetHeight for when box sizing is unreliable
6568	// We use getClientRects() to check for hidden/disconnected.
6569	// In those cases, the computed value can be trusted to be border-box
6570	if ( ( !support.boxSizingReliable() && isBorderBox ||
6571		val === "auto" ||
6572		!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
6573		elem.getClientRects().length ) {
6574
6575		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6576
6577		// Where available, offsetWidth/offsetHeight approximate border box dimensions.
6578		// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
6579		// retrieved value as a content box dimension.
6580		valueIsBorderBox = offsetProp in elem;
6581		if ( valueIsBorderBox ) {
6582			val = elem[ offsetProp ];
6583		}
6584	}
6585
6586	// Normalize "" and auto
6587	val = parseFloat( val ) || 0;
6588
6589	// Adjust for the element's box model
6590	return ( val +
6591		boxModelAdjustment(
6592			elem,
6593			dimension,
6594			extra || ( isBorderBox ? "border" : "content" ),
6595			valueIsBorderBox,
6596			styles,
6597
6598			// Provide the current computed size to request scroll gutter calculation (gh-3589)
6599			val
6600		)
6601	) + "px";
6602}
6603
6604jQuery.extend( {
6605
6606	// Add in style property hooks for overriding the default
6607	// behavior of getting and setting a style property
6608	cssHooks: {
6609		opacity: {
6610			get: function( elem, computed ) {
6611				if ( computed ) {
6612
6613					// We should always get a number back from opacity
6614					var ret = curCSS( elem, "opacity" );
6615					return ret === "" ? "1" : ret;
6616				}
6617			}
6618		}
6619	},
6620
6621	// Don't automatically add "px" to these possibly-unitless properties
6622	cssNumber: {
6623		"animationIterationCount": true,
6624		"columnCount": true,
6625		"fillOpacity": true,
6626		"flexGrow": true,
6627		"flexShrink": true,
6628		"fontWeight": true,
6629		"gridArea": true,
6630		"gridColumn": true,
6631		"gridColumnEnd": true,
6632		"gridColumnStart": true,
6633		"gridRow": true,
6634		"gridRowEnd": true,
6635		"gridRowStart": true,
6636		"lineHeight": true,
6637		"opacity": true,
6638		"order": true,
6639		"orphans": true,
6640		"widows": true,
6641		"zIndex": true,
6642		"zoom": true
6643	},
6644
6645	// Add in properties whose names you wish to fix before
6646	// setting or getting the value
6647	cssProps: {},
6648
6649	// Get and set the style property on a DOM Node
6650	style: function( elem, name, value, extra ) {
6651
6652		// Don't set styles on text and comment nodes
6653		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6654			return;
6655		}
6656
6657		// Make sure that we're working with the right name
6658		var ret, type, hooks,
6659			origName = camelCase( name ),
6660			isCustomProp = rcustomProp.test( name ),
6661			style = elem.style;
6662
6663		// Make sure that we're working with the right name. We don't
6664		// want to query the value if it is a CSS custom property
6665		// since they are user-defined.
6666		if ( !isCustomProp ) {
6667			name = finalPropName( origName );
6668		}
6669
6670		// Gets hook for the prefixed version, then unprefixed version
6671		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6672
6673		// Check if we're setting a value
6674		if ( value !== undefined ) {
6675			type = typeof value;
6676
6677			// Convert "+=" or "-=" to relative numbers (#7345)
6678			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
6679				value = adjustCSS( elem, name, ret );
6680
6681				// Fixes bug #9237
6682				type = "number";
6683			}
6684
6685			// Make sure that null and NaN values aren't set (#7116)
6686			if ( value == null || value !== value ) {
6687				return;
6688			}
6689
6690			// If a number was passed in, add the unit (except for certain CSS properties)
6691			// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
6692			// "px" to a few hardcoded values.
6693			if ( type === "number" && !isCustomProp ) {
6694				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6695			}
6696
6697			// background-* props affect original clone's values
6698			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
6699				style[ name ] = "inherit";
6700			}
6701
6702			// If a hook was provided, use that value, otherwise just set the specified value
6703			if ( !hooks || !( "set" in hooks ) ||
6704				( value = hooks.set( elem, value, extra ) ) !== undefined ) {
6705
6706				if ( isCustomProp ) {
6707					style.setProperty( name, value );
6708				} else {
6709					style[ name ] = value;
6710				}
6711			}
6712
6713		} else {
6714
6715			// If a hook was provided get the non-computed value from there
6716			if ( hooks && "get" in hooks &&
6717				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
6718
6719				return ret;
6720			}
6721
6722			// Otherwise just get the value from the style object
6723			return style[ name ];
6724		}
6725	},
6726
6727	css: function( elem, name, extra, styles ) {
6728		var val, num, hooks,
6729			origName = camelCase( name ),
6730			isCustomProp = rcustomProp.test( name );
6731
6732		// Make sure that we're working with the right name. We don't
6733		// want to modify the value if it is a CSS custom property
6734		// since they are user-defined.
6735		if ( !isCustomProp ) {
6736			name = finalPropName( origName );
6737		}
6738
6739		// Try prefixed name followed by the unprefixed name
6740		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6741
6742		// If a hook was provided get the computed value from there
6743		if ( hooks && "get" in hooks ) {
6744			val = hooks.get( elem, true, extra );
6745		}
6746
6747		// Otherwise, if a way to get the computed value exists, use that
6748		if ( val === undefined ) {
6749			val = curCSS( elem, name, styles );
6750		}
6751
6752		// Convert "normal" to computed value
6753		if ( val === "normal" && name in cssNormalTransform ) {
6754			val = cssNormalTransform[ name ];
6755		}
6756
6757		// Make numeric if forced or a qualifier was provided and val looks numeric
6758		if ( extra === "" || extra ) {
6759			num = parseFloat( val );
6760			return extra === true || isFinite( num ) ? num || 0 : val;
6761		}
6762
6763		return val;
6764	}
6765} );
6766
6767jQuery.each( [ "height", "width" ], function( i, dimension ) {
6768	jQuery.cssHooks[ dimension ] = {
6769		get: function( elem, computed, extra ) {
6770			if ( computed ) {
6771
6772				// Certain elements can have dimension info if we invisibly show them
6773				// but it must have a current display style that would benefit
6774				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
6775
6776					// Support: Safari 8+
6777					// Table columns in Safari have non-zero offsetWidth & zero
6778					// getBoundingClientRect().width unless display is changed.
6779					// Support: IE <=11 only
6780					// Running getBoundingClientRect on a disconnected node
6781					// in IE throws an error.
6782					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
6783						swap( elem, cssShow, function() {
6784							return getWidthOrHeight( elem, dimension, extra );
6785						} ) :
6786						getWidthOrHeight( elem, dimension, extra );
6787			}
6788		},
6789
6790		set: function( elem, value, extra ) {
6791			var matches,
6792				styles = getStyles( elem ),
6793
6794				// Only read styles.position if the test has a chance to fail
6795				// to avoid forcing a reflow.
6796				scrollboxSizeBuggy = !support.scrollboxSize() &&
6797					styles.position === "absolute",
6798
6799				// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
6800				boxSizingNeeded = scrollboxSizeBuggy || extra,
6801				isBorderBox = boxSizingNeeded &&
6802					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6803				subtract = extra ?
6804					boxModelAdjustment(
6805						elem,
6806						dimension,
6807						extra,
6808						isBorderBox,
6809						styles
6810					) :
6811					0;
6812
6813			// Account for unreliable border-box dimensions by comparing offset* to computed and
6814			// faking a content-box to get border and padding (gh-3699)
6815			if ( isBorderBox && scrollboxSizeBuggy ) {
6816				subtract -= Math.ceil(
6817					elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6818					parseFloat( styles[ dimension ] ) -
6819					boxModelAdjustment( elem, dimension, "border", false, styles ) -
6820					0.5
6821				);
6822			}
6823
6824			// Convert to pixels if value adjustment is needed
6825			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
6826				( matches[ 3 ] || "px" ) !== "px" ) {
6827
6828				elem.style[ dimension ] = value;
6829				value = jQuery.css( elem, dimension );
6830			}
6831
6832			return setPositiveNumber( elem, value, subtract );
6833		}
6834	};
6835} );
6836
6837jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
6838	function( elem, computed ) {
6839		if ( computed ) {
6840			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
6841				elem.getBoundingClientRect().left -
6842					swap( elem, { marginLeft: 0 }, function() {
6843						return elem.getBoundingClientRect().left;
6844					} )
6845				) + "px";
6846		}
6847	}
6848);
6849
6850// These hooks are used by animate to expand properties
6851jQuery.each( {
6852	margin: "",
6853	padding: "",
6854	border: "Width"
6855}, function( prefix, suffix ) {
6856	jQuery.cssHooks[ prefix + suffix ] = {
6857		expand: function( value ) {
6858			var i = 0,
6859				expanded = {},
6860
6861				// Assumes a single number if not a string
6862				parts = typeof value === "string" ? value.split( " " ) : [ value ];
6863
6864			for ( ; i < 4; i++ ) {
6865				expanded[ prefix + cssExpand[ i ] + suffix ] =
6866					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6867			}
6868
6869			return expanded;
6870		}
6871	};
6872
6873	if ( prefix !== "margin" ) {
6874		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6875	}
6876} );
6877
6878jQuery.fn.extend( {
6879	css: function( name, value ) {
6880		return access( this, function( elem, name, value ) {
6881			var styles, len,
6882				map = {},
6883				i = 0;
6884
6885			if ( Array.isArray( name ) ) {
6886				styles = getStyles( elem );
6887				len = name.length;
6888
6889				for ( ; i < len; i++ ) {
6890					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6891				}
6892
6893				return map;
6894			}
6895
6896			return value !== undefined ?
6897				jQuery.style( elem, name, value ) :
6898				jQuery.css( elem, name );
6899		}, name, value, arguments.length > 1 );
6900	}
6901} );
6902
6903
6904function Tween( elem, options, prop, end, easing ) {
6905	return new Tween.prototype.init( elem, options, prop, end, easing );
6906}
6907jQuery.Tween = Tween;
6908
6909Tween.prototype = {
6910	constructor: Tween,
6911	init: function( elem, options, prop, end, easing, unit ) {
6912		this.elem = elem;
6913		this.prop = prop;
6914		this.easing = easing || jQuery.easing._default;
6915		this.options = options;
6916		this.start = this.now = this.cur();
6917		this.end = end;
6918		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6919	},
6920	cur: function() {
6921		var hooks = Tween.propHooks[ this.prop ];
6922
6923		return hooks && hooks.get ?
6924			hooks.get( this ) :
6925			Tween.propHooks._default.get( this );
6926	},
6927	run: function( percent ) {
6928		var eased,
6929			hooks = Tween.propHooks[ this.prop ];
6930
6931		if ( this.options.duration ) {
6932			this.pos = eased = jQuery.easing[ this.easing ](
6933				percent, this.options.duration * percent, 0, 1, this.options.duration
6934			);
6935		} else {
6936			this.pos = eased = percent;
6937		}
6938		this.now = ( this.end - this.start ) * eased + this.start;
6939
6940		if ( this.options.step ) {
6941			this.options.step.call( this.elem, this.now, this );
6942		}
6943
6944		if ( hooks && hooks.set ) {
6945			hooks.set( this );
6946		} else {
6947			Tween.propHooks._default.set( this );
6948		}
6949		return this;
6950	}
6951};
6952
6953Tween.prototype.init.prototype = Tween.prototype;
6954
6955Tween.propHooks = {
6956	_default: {
6957		get: function( tween ) {
6958			var result;
6959
6960			// Use a property on the element directly when it is not a DOM element,
6961			// or when there is no matching style property that exists.
6962			if ( tween.elem.nodeType !== 1 ||
6963				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
6964				return tween.elem[ tween.prop ];
6965			}
6966
6967			// Passing an empty string as a 3rd parameter to .css will automatically
6968			// attempt a parseFloat and fallback to a string if the parse fails.
6969			// Simple values such as "10px" are parsed to Float;
6970			// complex values such as "rotate(1rad)" are returned as-is.
6971			result = jQuery.css( tween.elem, tween.prop, "" );
6972
6973			// Empty strings, null, undefined and "auto" are converted to 0.
6974			return !result || result === "auto" ? 0 : result;
6975		},
6976		set: function( tween ) {
6977
6978			// Use step hook for back compat.
6979			// Use cssHook if its there.
6980			// Use .style if available and use plain properties where available.
6981			if ( jQuery.fx.step[ tween.prop ] ) {
6982				jQuery.fx.step[ tween.prop ]( tween );
6983			} else if ( tween.elem.nodeType === 1 && (
6984					jQuery.cssHooks[ tween.prop ] ||
6985					tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
6986				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6987			} else {
6988				tween.elem[ tween.prop ] = tween.now;
6989			}
6990		}
6991	}
6992};
6993
6994// Support: IE <=9 only
6995// Panic based approach to setting things on disconnected nodes
6996Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
6997	set: function( tween ) {
6998		if ( tween.elem.nodeType && tween.elem.parentNode ) {
6999			tween.elem[ tween.prop ] = tween.now;
7000		}
7001	}
7002};
7003
7004jQuery.easing = {
7005	linear: function( p ) {
7006		return p;
7007	},
7008	swing: function( p ) {
7009		return 0.5 - Math.cos( p * Math.PI ) / 2;
7010	},
7011	_default: "swing"
7012};
7013
7014jQuery.fx = Tween.prototype.init;
7015
7016// Back compat <1.8 extension point
7017jQuery.fx.step = {};
7018
7019
7020
7021
7022var
7023	fxNow, inProgress,
7024	rfxtypes = /^(?:toggle|show|hide)$/,
7025	rrun = /queueHooks$/;
7026
7027function schedule() {
7028	if ( inProgress ) {
7029		if ( document.hidden === false && window.requestAnimationFrame ) {
7030			window.requestAnimationFrame( schedule );
7031		} else {
7032			window.setTimeout( schedule, jQuery.fx.interval );
7033		}
7034
7035		jQuery.fx.tick();
7036	}
7037}
7038
7039// Animations created synchronously will run synchronously
7040function createFxNow() {
7041	window.setTimeout( function() {
7042		fxNow = undefined;
7043	} );
7044	return ( fxNow = Date.now() );
7045}
7046
7047// Generate parameters to create a standard animation
7048function genFx( type, includeWidth ) {
7049	var which,
7050		i = 0,
7051		attrs = { height: type };
7052
7053	// If we include width, step value is 1 to do all cssExpand values,
7054	// otherwise step value is 2 to skip over Left and Right
7055	includeWidth = includeWidth ? 1 : 0;
7056	for ( ; i < 4; i += 2 - includeWidth ) {
7057		which = cssExpand[ i ];
7058		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7059	}
7060
7061	if ( includeWidth ) {
7062		attrs.opacity = attrs.width = type;
7063	}
7064
7065	return attrs;
7066}
7067
7068function createTween( value, prop, animation ) {
7069	var tween,
7070		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
7071		index = 0,
7072		length = collection.length;
7073	for ( ; index < length; index++ ) {
7074		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
7075
7076			// We're done with this property
7077			return tween;
7078		}
7079	}
7080}
7081
7082function defaultPrefilter( elem, props, opts ) {
7083	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
7084		isBox = "width" in props || "height" in props,
7085		anim = this,
7086		orig = {},
7087		style = elem.style,
7088		hidden = elem.nodeType && isHiddenWithinTree( elem ),
7089		dataShow = dataPriv.get( elem, "fxshow" );
7090
7091	// Queue-skipping animations hijack the fx hooks
7092	if ( !opts.queue ) {
7093		hooks = jQuery._queueHooks( elem, "fx" );
7094		if ( hooks.unqueued == null ) {
7095			hooks.unqueued = 0;
7096			oldfire = hooks.empty.fire;
7097			hooks.empty.fire = function() {
7098				if ( !hooks.unqueued ) {
7099					oldfire();
7100				}
7101			};
7102		}
7103		hooks.unqueued++;
7104
7105		anim.always( function() {
7106
7107			// Ensure the complete handler is called before this completes
7108			anim.always( function() {
7109				hooks.unqueued--;
7110				if ( !jQuery.queue( elem, "fx" ).length ) {
7111					hooks.empty.fire();
7112				}
7113			} );
7114		} );
7115	}
7116
7117	// Detect show/hide animations
7118	for ( prop in props ) {
7119		value = props[ prop ];
7120		if ( rfxtypes.test( value ) ) {
7121			delete props[ prop ];
7122			toggle = toggle || value === "toggle";
7123			if ( value === ( hidden ? "hide" : "show" ) ) {
7124
7125				// Pretend to be hidden if this is a "show" and
7126				// there is still data from a stopped show/hide
7127				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7128					hidden = true;
7129
7130				// Ignore all other no-op show/hide data
7131				} else {
7132					continue;
7133				}
7134			}
7135			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7136		}
7137	}
7138
7139	// Bail out if this is a no-op like .hide().hide()
7140	propTween = !jQuery.isEmptyObject( props );
7141	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
7142		return;
7143	}
7144
7145	// Restrict "overflow" and "display" styles during box animations
7146	if ( isBox && elem.nodeType === 1 ) {
7147
vendor: 4,220 bytes, lines 7148-7307
7148		// Support: IE <=9 - 11, Edge 12 - 15
7149		// Record all 3 overflow attributes because IE does not infer the shorthand
7150		// from identically-valued overflowX and overflowY and Edge just mirrors
7151		// the overflowX value there.
7152		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7153
7154		// Identify a display type, preferring old show/hide data over the CSS cascade
7155		restoreDisplay = dataShow && dataShow.display;
7156		if ( restoreDisplay == null ) {
7157			restoreDisplay = dataPriv.get( elem, "display" );
7158		}
7159		display = jQuery.css( elem, "display" );
7160		if ( display === "none" ) {
7161			if ( restoreDisplay ) {
7162				display = restoreDisplay;
7163			} else {
7164
7165				// Get nonempty value(s) by temporarily forcing visibility
7166				showHide( [ elem ], true );
7167				restoreDisplay = elem.style.display || restoreDisplay;
7168				display = jQuery.css( elem, "display" );
7169				showHide( [ elem ] );
7170			}
7171		}
7172
7173		// Animate inline elements as inline-block
7174		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
7175			if ( jQuery.css( elem, "float" ) === "none" ) {
7176
7177				// Restore the original display value at the end of pure show/hide animations
7178				if ( !propTween ) {
7179					anim.done( function() {
7180						style.display = restoreDisplay;
7181					} );
7182					if ( restoreDisplay == null ) {
7183						display = style.display;
7184						restoreDisplay = display === "none" ? "" : display;
7185					}
7186				}
7187				style.display = "inline-block";
7188			}
7189		}
7190	}
7191
7192	if ( opts.overflow ) {
7193		style.overflow = "hidden";
7194		anim.always( function() {
7195			style.overflow = opts.overflow[ 0 ];
7196			style.overflowX = opts.overflow[ 1 ];
7197			style.overflowY = opts.overflow[ 2 ];
7198		} );
7199	}
7200
7201	// Implement show/hide animations
7202	propTween = false;
7203	for ( prop in orig ) {
7204
7205		// General show/hide setup for this element animation
7206		if ( !propTween ) {
7207			if ( dataShow ) {
7208				if ( "hidden" in dataShow ) {
7209					hidden = dataShow.hidden;
7210				}
7211			} else {
7212				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
7213			}
7214
7215			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
7216			if ( toggle ) {
7217				dataShow.hidden = !hidden;
7218			}
7219
7220			// Show elements before animating them
7221			if ( hidden ) {
7222				showHide( [ elem ], true );
7223			}
7224
7225			/* eslint-disable no-loop-func */
7226
7227			anim.done( function() {
7228
7229			/* eslint-enable no-loop-func */
7230
7231				// The final step of a "hide" animation is actually hiding the element
7232				if ( !hidden ) {
7233					showHide( [ elem ] );
7234				}
7235				dataPriv.remove( elem, "fxshow" );
7236				for ( prop in orig ) {
7237					jQuery.style( elem, prop, orig[ prop ] );
7238				}
7239			} );
7240		}
7241
7242		// Per-property setup
7243		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7244		if ( !( prop in dataShow ) ) {
7245			dataShow[ prop ] = propTween.start;
7246			if ( hidden ) {
7247				propTween.end = propTween.start;
7248				propTween.start = 0;
7249			}
7250		}
7251	}
7252}
7253
7254function propFilter( props, specialEasing ) {
7255	var index, name, easing, value, hooks;
7256
7257	// camelCase, specialEasing and expand cssHook pass
7258	for ( index in props ) {
7259		name = camelCase( index );
7260		easing = specialEasing[ name ];
7261		value = props[ index ];
7262		if ( Array.isArray( value ) ) {
7263			easing = value[ 1 ];
7264			value = props[ index ] = value[ 0 ];
7265		}
7266
7267		if ( index !== name ) {
7268			props[ name ] = value;
7269			delete props[ index ];
7270		}
7271
7272		hooks = jQuery.cssHooks[ name ];
7273		if ( hooks && "expand" in hooks ) {
7274			value = hooks.expand( value );
7275			delete props[ name ];
7276
7277			// Not quite $.extend, this won't overwrite existing keys.
7278			// Reusing 'index' because we have the correct "name"
7279			for ( index in value ) {
7280				if ( !( index in props ) ) {
7281					props[ index ] = value[ index ];
7282					specialEasing[ index ] = easing;
7283				}
7284			}
7285		} else {
7286			specialEasing[ name ] = easing;
7287		}
7288	}
7289}
7290
7291function Animation( elem, properties, options ) {
7292	var result,
7293		stopped,
7294		index = 0,
7295		length = Animation.prefilters.length,
7296		deferred = jQuery.Deferred().always( function() {
7297
7298			// Don't match elem in the :animated selector
7299			delete tick.elem;
7300		} ),
7301		tick = function() {
7302			if ( stopped ) {
7303				return false;
7304			}
7305			var currentTime = fxNow || createFxNow(),
7306				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7307
vendor: 20,984 bytes, lines 7308-8178
7308				// Support: Android 2.3 only
7309				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
7310				temp = remaining / animation.duration || 0,
7311				percent = 1 - temp,
7312				index = 0,
7313				length = animation.tweens.length;
7314
7315			for ( ; index < length; index++ ) {
7316				animation.tweens[ index ].run( percent );
7317			}
7318
7319			deferred.notifyWith( elem, [ animation, percent, remaining ] );
7320
7321			// If there's more to do, yield
7322			if ( percent < 1 && length ) {
7323				return remaining;
7324			}
7325
7326			// If this was an empty animation, synthesize a final progress notification
7327			if ( !length ) {
7328				deferred.notifyWith( elem, [ animation, 1, 0 ] );
7329			}
7330
7331			// Resolve the animation and report its conclusion
7332			deferred.resolveWith( elem, [ animation ] );
7333			return false;
7334		},
7335		animation = deferred.promise( {
7336			elem: elem,
7337			props: jQuery.extend( {}, properties ),
7338			opts: jQuery.extend( true, {
7339				specialEasing: {},
7340				easing: jQuery.easing._default
7341			}, options ),
7342			originalProperties: properties,
7343			originalOptions: options,
7344			startTime: fxNow || createFxNow(),
7345			duration: options.duration,
7346			tweens: [],
7347			createTween: function( prop, end ) {
7348				var tween = jQuery.Tween( elem, animation.opts, prop, end,
7349						animation.opts.specialEasing[ prop ] || animation.opts.easing );
7350				animation.tweens.push( tween );
7351				return tween;
7352			},
7353			stop: function( gotoEnd ) {
7354				var index = 0,
7355
7356					// If we are going to the end, we want to run all the tweens
7357					// otherwise we skip this part
7358					length = gotoEnd ? animation.tweens.length : 0;
7359				if ( stopped ) {
7360					return this;
7361				}
7362				stopped = true;
7363				for ( ; index < length; index++ ) {
7364					animation.tweens[ index ].run( 1 );
7365				}
7366
7367				// Resolve when we played the last frame; otherwise, reject
7368				if ( gotoEnd ) {
7369					deferred.notifyWith( elem, [ animation, 1, 0 ] );
7370					deferred.resolveWith( elem, [ animation, gotoEnd ] );
7371				} else {
7372					deferred.rejectWith( elem, [ animation, gotoEnd ] );
7373				}
7374				return this;
7375			}
7376		} ),
7377		props = animation.props;
7378
7379	propFilter( props, animation.opts.specialEasing );
7380
7381	for ( ; index < length; index++ ) {
7382		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
7383		if ( result ) {
7384			if ( isFunction( result.stop ) ) {
7385				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
7386					result.stop.bind( result );
7387			}
7388			return result;
7389		}
7390	}
7391
7392	jQuery.map( props, createTween, animation );
7393
7394	if ( isFunction( animation.opts.start ) ) {
7395		animation.opts.start.call( elem, animation );
7396	}
7397
7398	// Attach callbacks from options
7399	animation
7400		.progress( animation.opts.progress )
7401		.done( animation.opts.done, animation.opts.complete )
7402		.fail( animation.opts.fail )
7403		.always( animation.opts.always );
7404
7405	jQuery.fx.timer(
7406		jQuery.extend( tick, {
7407			elem: elem,
7408			anim: animation,
7409			queue: animation.opts.queue
7410		} )
7411	);
7412
7413	return animation;
7414}
7415
7416jQuery.Animation = jQuery.extend( Animation, {
7417
7418	tweeners: {
7419		"*": [ function( prop, value ) {
7420			var tween = this.createTween( prop, value );
7421			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
7422			return tween;
7423		} ]
7424	},
7425
7426	tweener: function( props, callback ) {
7427		if ( isFunction( props ) ) {
7428			callback = props;
7429			props = [ "*" ];
7430		} else {
7431			props = props.match( rnothtmlwhite );
7432		}
7433
7434		var prop,
7435			index = 0,
7436			length = props.length;
7437
7438		for ( ; index < length; index++ ) {
7439			prop = props[ index ];
7440			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
7441			Animation.tweeners[ prop ].unshift( callback );
7442		}
7443	},
7444
7445	prefilters: [ defaultPrefilter ],
7446
7447	prefilter: function( callback, prepend ) {
7448		if ( prepend ) {
7449			Animation.prefilters.unshift( callback );
7450		} else {
7451			Animation.prefilters.push( callback );
7452		}
7453	}
7454} );
7455
7456jQuery.speed = function( speed, easing, fn ) {
7457	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7458		complete: fn || !fn && easing ||
7459			isFunction( speed ) && speed,
7460		duration: speed,
7461		easing: fn && easing || easing && !isFunction( easing ) && easing
7462	};
7463
7464	// Go to the end state if fx are off
7465	if ( jQuery.fx.off ) {
7466		opt.duration = 0;
7467
7468	} else {
7469		if ( typeof opt.duration !== "number" ) {
7470			if ( opt.duration in jQuery.fx.speeds ) {
7471				opt.duration = jQuery.fx.speeds[ opt.duration ];
7472
7473			} else {
7474				opt.duration = jQuery.fx.speeds._default;
7475			}
7476		}
7477	}
7478
7479	// Normalize opt.queue - true/undefined/null -> "fx"
7480	if ( opt.queue == null || opt.queue === true ) {
7481		opt.queue = "fx";
7482	}
7483
7484	// Queueing
7485	opt.old = opt.complete;
7486
7487	opt.complete = function() {
7488		if ( isFunction( opt.old ) ) {
7489			opt.old.call( this );
7490		}
7491
7492		if ( opt.queue ) {
7493			jQuery.dequeue( this, opt.queue );
7494		}
7495	};
7496
7497	return opt;
7498};
7499
7500jQuery.fn.extend( {
7501	fadeTo: function( speed, to, easing, callback ) {
7502
7503		// Show any hidden elements after setting opacity to 0
7504		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
7505
7506			// Animate to the value specified
7507			.end().animate( { opacity: to }, speed, easing, callback );
7508	},
7509	animate: function( prop, speed, easing, callback ) {
7510		var empty = jQuery.isEmptyObject( prop ),
7511			optall = jQuery.speed( speed, easing, callback ),
7512			doAnimation = function() {
7513
7514				// Operate on a copy of prop so per-property easing won't be lost
7515				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7516
7517				// Empty animations, or finishing resolves immediately
7518				if ( empty || dataPriv.get( this, "finish" ) ) {
7519					anim.stop( true );
7520				}
7521			};
7522			doAnimation.finish = doAnimation;
7523
7524		return empty || optall.queue === false ?
7525			this.each( doAnimation ) :
7526			this.queue( optall.queue, doAnimation );
7527	},
7528	stop: function( type, clearQueue, gotoEnd ) {
7529		var stopQueue = function( hooks ) {
7530			var stop = hooks.stop;
7531			delete hooks.stop;
7532			stop( gotoEnd );
7533		};
7534
7535		if ( typeof type !== "string" ) {
7536			gotoEnd = clearQueue;
7537			clearQueue = type;
7538			type = undefined;
7539		}
7540		if ( clearQueue && type !== false ) {
7541			this.queue( type || "fx", [] );
7542		}
7543
7544		return this.each( function() {
7545			var dequeue = true,
7546				index = type != null && type + "queueHooks",
7547				timers = jQuery.timers,
7548				data = dataPriv.get( this );
7549
7550			if ( index ) {
7551				if ( data[ index ] && data[ index ].stop ) {
7552					stopQueue( data[ index ] );
7553				}
7554			} else {
7555				for ( index in data ) {
7556					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7557						stopQueue( data[ index ] );
7558					}
7559				}
7560			}
7561
7562			for ( index = timers.length; index--; ) {
7563				if ( timers[ index ].elem === this &&
7564					( type == null || timers[ index ].queue === type ) ) {
7565
7566					timers[ index ].anim.stop( gotoEnd );
7567					dequeue = false;
7568					timers.splice( index, 1 );
7569				}
7570			}
7571
7572			// Start the next in the queue if the last step wasn't forced.
7573			// Timers currently will call their complete callbacks, which
7574			// will dequeue but only if they were gotoEnd.
7575			if ( dequeue || !gotoEnd ) {
7576				jQuery.dequeue( this, type );
7577			}
7578		} );
7579	},
7580	finish: function( type ) {
7581		if ( type !== false ) {
7582			type = type || "fx";
7583		}
7584		return this.each( function() {
7585			var index,
7586				data = dataPriv.get( this ),
7587				queue = data[ type + "queue" ],
7588				hooks = data[ type + "queueHooks" ],
7589				timers = jQuery.timers,
7590				length = queue ? queue.length : 0;
7591
7592			// Enable finishing flag on private data
7593			data.finish = true;
7594
7595			// Empty the queue first
7596			jQuery.queue( this, type, [] );
7597
7598			if ( hooks && hooks.stop ) {
7599				hooks.stop.call( this, true );
7600			}
7601
7602			// Look for any active animations, and finish them
7603			for ( index = timers.length; index--; ) {
7604				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7605					timers[ index ].anim.stop( true );
7606					timers.splice( index, 1 );
7607				}
7608			}
7609
7610			// Look for any animations in the old queue and finish them
7611			for ( index = 0; index < length; index++ ) {
7612				if ( queue[ index ] && queue[ index ].finish ) {
7613					queue[ index ].finish.call( this );
7614				}
7615			}
7616
7617			// Turn off finishing flag
7618			delete data.finish;
7619		} );
7620	}
7621} );
7622
7623jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
7624	var cssFn = jQuery.fn[ name ];
7625	jQuery.fn[ name ] = function( speed, easing, callback ) {
7626		return speed == null || typeof speed === "boolean" ?
7627			cssFn.apply( this, arguments ) :
7628			this.animate( genFx( name, true ), speed, easing, callback );
7629	};
7630} );
7631
7632// Generate shortcuts for custom animations
7633jQuery.each( {
7634	slideDown: genFx( "show" ),
7635	slideUp: genFx( "hide" ),
7636	slideToggle: genFx( "toggle" ),
7637	fadeIn: { opacity: "show" },
7638	fadeOut: { opacity: "hide" },
7639	fadeToggle: { opacity: "toggle" }
7640}, function( name, props ) {
7641	jQuery.fn[ name ] = function( speed, easing, callback ) {
7642		return this.animate( props, speed, easing, callback );
7643	};
7644} );
7645
7646jQuery.timers = [];
7647jQuery.fx.tick = function() {
7648	var timer,
7649		i = 0,
7650		timers = jQuery.timers;
7651
7652	fxNow = Date.now();
7653
7654	for ( ; i < timers.length; i++ ) {
7655		timer = timers[ i ];
7656
7657		// Run the timer and safely remove it when done (allowing for external removal)
7658		if ( !timer() && timers[ i ] === timer ) {
7659			timers.splice( i--, 1 );
7660		}
7661	}
7662
7663	if ( !timers.length ) {
7664		jQuery.fx.stop();
7665	}
7666	fxNow = undefined;
7667};
7668
7669jQuery.fx.timer = function( timer ) {
7670	jQuery.timers.push( timer );
7671	jQuery.fx.start();
7672};
7673
7674jQuery.fx.interval = 13;
7675jQuery.fx.start = function() {
7676	if ( inProgress ) {
7677		return;
7678	}
7679
7680	inProgress = true;
7681	schedule();
7682};
7683
7684jQuery.fx.stop = function() {
7685	inProgress = null;
7686};
7687
7688jQuery.fx.speeds = {
7689	slow: 600,
7690	fast: 200,
7691
7692	// Default speed
7693	_default: 400
7694};
7695
7696
7697// Based off of the plugin by Clint Helfers, with permission.
7698// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
7699jQuery.fn.delay = function( time, type ) {
7700	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7701	type = type || "fx";
7702
7703	return this.queue( type, function( next, hooks ) {
7704		var timeout = window.setTimeout( next, time );
7705		hooks.stop = function() {
7706			window.clearTimeout( timeout );
7707		};
7708	} );
7709};
7710
7711
7712( function() {
7713	var input = document.createElement( "input" ),
7714		select = document.createElement( "select" ),
7715		opt = select.appendChild( document.createElement( "option" ) );
7716
7717	input.type = "checkbox";
7718
7719	// Support: Android <=4.3 only
7720	// Default value for a checkbox should be "on"
7721	support.checkOn = input.value !== "";
7722
7723	// Support: IE <=11 only
7724	// Must access selectedIndex to make default options select
7725	support.optSelected = opt.selected;
7726
7727	// Support: IE <=11 only
7728	// An input loses its value after becoming a radio
7729	input = document.createElement( "input" );
7730	input.value = "t";
7731	input.type = "radio";
7732	support.radioValue = input.value === "t";
7733} )();
7734
7735
7736var boolHook,
7737	attrHandle = jQuery.expr.attrHandle;
7738
7739jQuery.fn.extend( {
7740	attr: function( name, value ) {
7741		return access( this, jQuery.attr, name, value, arguments.length > 1 );
7742	},
7743
7744	removeAttr: function( name ) {
7745		return this.each( function() {
7746			jQuery.removeAttr( this, name );
7747		} );
7748	}
7749} );
7750
7751jQuery.extend( {
7752	attr: function( elem, name, value ) {
7753		var ret, hooks,
7754			nType = elem.nodeType;
7755
7756		// Don't get/set attributes on text, comment and attribute nodes
7757		if ( nType === 3 || nType === 8 || nType === 2 ) {
7758			return;
7759		}
7760
7761		// Fallback to prop when attributes are not supported
7762		if ( typeof elem.getAttribute === "undefined" ) {
7763			return jQuery.prop( elem, name, value );
7764		}
7765
7766		// Attribute hooks are determined by the lowercase version
7767		// Grab necessary hook if one is defined
7768		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7769			hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
7770				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
7771		}
7772
7773		if ( value !== undefined ) {
7774			if ( value === null ) {
7775				jQuery.removeAttr( elem, name );
7776				return;
7777			}
7778
7779			if ( hooks && "set" in hooks &&
7780				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7781				return ret;
7782			}
7783
7784			elem.setAttribute( name, value + "" );
7785			return value;
7786		}
7787
7788		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7789			return ret;
7790		}
7791
7792		ret = jQuery.find.attr( elem, name );
7793
7794		// Non-existent attributes return null, we normalize to undefined
7795		return ret == null ? undefined : ret;
7796	},
7797
7798	attrHooks: {
7799		type: {
7800			set: function( elem, value ) {
7801				if ( !support.radioValue && value === "radio" &&
7802					nodeName( elem, "input" ) ) {
7803					var val = elem.value;
7804					elem.setAttribute( "type", value );
7805					if ( val ) {
7806						elem.value = val;
7807					}
7808					return value;
7809				}
7810			}
7811		}
7812	},
7813
7814	removeAttr: function( elem, value ) {
7815		var name,
7816			i = 0,
7817
7818			// Attribute names can contain non-HTML whitespace characters
7819			// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
7820			attrNames = value && value.match( rnothtmlwhite );
7821
7822		if ( attrNames && elem.nodeType === 1 ) {
7823			while ( ( name = attrNames[ i++ ] ) ) {
7824				elem.removeAttribute( name );
7825			}
7826		}
7827	}
7828} );
7829
7830// Hooks for boolean attributes
7831boolHook = {
7832	set: function( elem, value, name ) {
7833		if ( value === false ) {
7834
7835			// Remove boolean attributes when set to false
7836			jQuery.removeAttr( elem, name );
7837		} else {
7838			elem.setAttribute( name, name );
7839		}
7840		return name;
7841	}
7842};
7843
7844jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
7845	var getter = attrHandle[ name ] || jQuery.find.attr;
7846
7847	attrHandle[ name ] = function( elem, name, isXML ) {
7848		var ret, handle,
7849			lowercaseName = name.toLowerCase();
7850
7851		if ( !isXML ) {
7852
7853			// Avoid an infinite loop by temporarily removing this function from the getter
7854			handle = attrHandle[ lowercaseName ];
7855			attrHandle[ lowercaseName ] = ret;
7856			ret = getter( elem, name, isXML ) != null ?
7857				lowercaseName :
7858				null;
7859			attrHandle[ lowercaseName ] = handle;
7860		}
7861		return ret;
7862	};
7863} );
7864
7865
7866
7867
7868var rfocusable = /^(?:input|select|textarea|button)$/i,
7869	rclickable = /^(?:a|area)$/i;
7870
7871jQuery.fn.extend( {
7872	prop: function( name, value ) {
7873		return access( this, jQuery.prop, name, value, arguments.length > 1 );
7874	},
7875
7876	removeProp: function( name ) {
7877		return this.each( function() {
7878			delete this[ jQuery.propFix[ name ] || name ];
7879		} );
7880	}
7881} );
7882
7883jQuery.extend( {
7884	prop: function( elem, name, value ) {
7885		var ret, hooks,
7886			nType = elem.nodeType;
7887
7888		// Don't get/set properties on text, comment and attribute nodes
7889		if ( nType === 3 || nType === 8 || nType === 2 ) {
7890			return;
7891		}
7892
7893		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7894
7895			// Fix name and attach hooks
7896			name = jQuery.propFix[ name ] || name;
7897			hooks = jQuery.propHooks[ name ];
7898		}
7899
7900		if ( value !== undefined ) {
7901			if ( hooks && "set" in hooks &&
7902				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7903				return ret;
7904			}
7905
7906			return ( elem[ name ] = value );
7907		}
7908
7909		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7910			return ret;
7911		}
7912
7913		return elem[ name ];
7914	},
7915
7916	propHooks: {
7917		tabIndex: {
7918			get: function( elem ) {
7919
7920				// Support: IE <=9 - 11 only
7921				// elem.tabIndex doesn't always return the
7922				// correct value when it hasn't been explicitly set
7923				// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
7924				// Use proper attribute retrieval(#12072)
7925				var tabindex = jQuery.find.attr( elem, "tabindex" );
7926
7927				if ( tabindex ) {
7928					return parseInt( tabindex, 10 );
7929				}
7930
7931				if (
7932					rfocusable.test( elem.nodeName ) ||
7933					rclickable.test( elem.nodeName ) &&
7934					elem.href
7935				) {
7936					return 0;
7937				}
7938
7939				return -1;
7940			}
7941		}
7942	},
7943
7944	propFix: {
7945		"for": "htmlFor",
7946		"class": "className"
7947	}
7948} );
7949
7950// Support: IE <=11 only
7951// Accessing the selectedIndex property
7952// forces the browser to respect setting selected
7953// on the option
7954// The getter ensures a default option is selected
7955// when in an optgroup
7956// eslint rule "no-unused-expressions" is disabled for this code
7957// since it considers such accessions noop
7958if ( !support.optSelected ) {
7959	jQuery.propHooks.selected = {
7960		get: function( elem ) {
7961
7962			/* eslint no-unused-expressions: "off" */
7963
7964			var parent = elem.parentNode;
7965			if ( parent && parent.parentNode ) {
7966				parent.parentNode.selectedIndex;
7967			}
7968			return null;
7969		},
7970		set: function( elem ) {
7971
7972			/* eslint no-unused-expressions: "off" */
7973
7974			var parent = elem.parentNode;
7975			if ( parent ) {
7976				parent.selectedIndex;
7977
7978				if ( parent.parentNode ) {
7979					parent.parentNode.selectedIndex;
7980				}
7981			}
7982		}
7983	};
7984}
7985
7986jQuery.each( [
7987	"tabIndex",
7988	"readOnly",
7989	"maxLength",
7990	"cellSpacing",
7991	"cellPadding",
7992	"rowSpan",
7993	"colSpan",
7994	"useMap",
7995	"frameBorder",
7996	"contentEditable"
7997], function() {
7998	jQuery.propFix[ this.toLowerCase() ] = this;
7999} );
8000
8001
8002
8003
8004	// Strip and collapse whitespace according to HTML spec
8005	// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
8006	function stripAndCollapse( value ) {
8007		var tokens = value.match( rnothtmlwhite ) || [];
8008		return tokens.join( " " );
8009	}
8010
8011
8012function getClass( elem ) {
8013	return elem.getAttribute && elem.getAttribute( "class" ) || "";
8014}
8015
8016function classesToArray( value ) {
8017	if ( Array.isArray( value ) ) {
8018		return value;
8019	}
8020	if ( typeof value === "string" ) {
8021		return value.match( rnothtmlwhite ) || [];
8022	}
8023	return [];
8024}
8025
8026jQuery.fn.extend( {
8027	addClass: function( value ) {
8028		var classes, elem, cur, curValue, clazz, j, finalValue,
8029			i = 0;
8030
8031		if ( isFunction( value ) ) {
8032			return this.each( function( j ) {
8033				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
8034			} );
8035		}
8036
8037		classes = classesToArray( value );
8038
8039		if ( classes.length ) {
8040			while ( ( elem = this[ i++ ] ) ) {
8041				curValue = getClass( elem );
8042				cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8043
8044				if ( cur ) {
8045					j = 0;
8046					while ( ( clazz = classes[ j++ ] ) ) {
8047						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
8048							cur += clazz + " ";
8049						}
8050					}
8051
8052					// Only assign if different to avoid unneeded rendering.
8053					finalValue = stripAndCollapse( cur );
8054					if ( curValue !== finalValue ) {
8055						elem.setAttribute( "class", finalValue );
8056					}
8057				}
8058			}
8059		}
8060
8061		return this;
8062	},
8063
8064	removeClass: function( value ) {
8065		var classes, elem, cur, curValue, clazz, j, finalValue,
8066			i = 0;
8067
8068		if ( isFunction( value ) ) {
8069			return this.each( function( j ) {
8070				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
8071			} );
8072		}
8073
8074		if ( !arguments.length ) {
8075			return this.attr( "class", "" );
8076		}
8077
8078		classes = classesToArray( value );
8079
8080		if ( classes.length ) {
8081			while ( ( elem = this[ i++ ] ) ) {
8082				curValue = getClass( elem );
8083
8084				// This expression is here for better compressibility (see addClass)
8085				cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
8086
8087				if ( cur ) {
8088					j = 0;
8089					while ( ( clazz = classes[ j++ ] ) ) {
8090
8091						// Remove *all* instances
8092						while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
8093							cur = cur.replace( " " + clazz + " ", " " );
8094						}
8095					}
8096
8097					// Only assign if different to avoid unneeded rendering.
8098					finalValue = stripAndCollapse( cur );
8099					if ( curValue !== finalValue ) {
8100						elem.setAttribute( "class", finalValue );
8101					}
8102				}
8103			}
8104		}
8105
8106		return this;
8107	},
8108
8109	toggleClass: function( value, stateVal ) {
8110		var type = typeof value,
8111			isValidValue = type === "string" || Array.isArray( value );
8112
8113		if ( typeof stateVal === "boolean" && isValidValue ) {
8114			return stateVal ? this.addClass( value ) : this.removeClass( value );
8115		}
8116
8117		if ( isFunction( value ) ) {
8118			return this.each( function( i ) {
8119				jQuery( this ).toggleClass(
8120					value.call( this, i, getClass( this ), stateVal ),
8121					stateVal
8122				);
8123			} );
8124		}
8125
8126		return this.each( function() {
8127			var className, i, self, classNames;
8128
8129			if ( isValidValue ) {
8130
8131				// Toggle individual class names
8132				i = 0;
8133				self = jQuery( this );
8134				classNames = classesToArray( value );
8135
8136				while ( ( className = classNames[ i++ ] ) ) {
8137
8138					// Check each className given, space separated list
8139					if ( self.hasClass( className ) ) {
8140						self.removeClass( className );
8141					} else {
8142						self.addClass( className );
8143					}
8144				}
8145
8146			// Toggle whole class name
8147			} else if ( value === undefined || type === "boolean" ) {
8148				className = getClass( this );
8149				if ( className ) {
8150
8151					// Store className if set
8152					dataPriv.set( this, "__className__", className );
8153				}
8154
8155				// If the element has a class name or if we're passed `false`,
8156				// then remove the whole classname (if there was one, the above saved it).
8157				// Otherwise bring back whatever was previously saved (if anything),
8158				// falling back to the empty string if nothing was stored.
8159				if ( this.setAttribute ) {
8160					this.setAttribute( "class",
8161						className || value === false ?
8162						"" :
8163						dataPriv.get( this, "__className__" ) || ""
8164					);
8165				}
8166			}
8167		} );
8168	},
8169
8170	hasClass: function( selector ) {
8171		var className, elem,
8172			i = 0;
8173
8174		className = " " + selector + " ";
8175		while ( ( elem = this[ i++ ] ) ) {
8176			if ( elem.nodeType === 1 &&
8177				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
8178	
vendor: 1,792 bytes, lines 8178-8270
8178				return true;
8179			}
8180		}
8181
8182		return false;
8183	}
8184} );
8185
8186
8187
8188
8189var rreturn = /\r/g;
8190
8191jQuery.fn.extend( {
8192	val: function( value ) {
8193		var hooks, ret, valueIsFunction,
8194			elem = this[ 0 ];
8195
8196		if ( !arguments.length ) {
8197			if ( elem ) {
8198				hooks = jQuery.valHooks[ elem.type ] ||
8199					jQuery.valHooks[ elem.nodeName.toLowerCase() ];
8200
8201				if ( hooks &&
8202					"get" in hooks &&
8203					( ret = hooks.get( elem, "value" ) ) !== undefined
8204				) {
8205					return ret;
8206				}
8207
8208				ret = elem.value;
8209
8210				// Handle most common string cases
8211				if ( typeof ret === "string" ) {
8212					return ret.replace( rreturn, "" );
8213				}
8214
8215				// Handle cases where value is null/undef or number
8216				return ret == null ? "" : ret;
8217			}
8218
8219			return;
8220		}
8221
8222		valueIsFunction = isFunction( value );
8223
8224		return this.each( function( i ) {
8225			var val;
8226
8227			if ( this.nodeType !== 1 ) {
8228				return;
8229			}
8230
8231			if ( valueIsFunction ) {
8232				val = value.call( this, i, jQuery( this ).val() );
8233			} else {
8234				val = value;
8235			}
8236
8237			// Treat null/undefined as ""; convert numbers to string
8238			if ( val == null ) {
8239				val = "";
8240
8241			} else if ( typeof val === "number" ) {
8242				val += "";
8243
8244			} else if ( Array.isArray( val ) ) {
8245				val = jQuery.map( val, function( value ) {
8246					return value == null ? "" : value + "";
8247				} );
8248			}
8249
8250			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
8251
8252			// If set returns undefined, fall back to normal setting
8253			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
8254				this.value = val;
8255			}
8256		} );
8257	}
8258} );
8259
8260jQuery.extend( {
8261	valHooks: {
8262		option: {
8263			get: function( elem ) {
8264
8265				var val = jQuery.find.attr( elem, "value" );
8266				return val != null ?
8267					val :
8268
8269					// Support: IE <=10 - 11 only
8270					// option.text throws exceptions (
vendor: 15,164 bytes, lines 8270-8841
8270#14686, #14858)
8271					// Strip and collapse whitespace
8272					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8273					stripAndCollapse( jQuery.text( elem ) );
8274			}
8275		},
8276		select: {
8277			get: function( elem ) {
8278				var value, option, i,
8279					options = elem.options,
8280					index = elem.selectedIndex,
8281					one = elem.type === "select-one",
8282					values = one ? null : [],
8283					max = one ? index + 1 : options.length;
8284
8285				if ( index < 0 ) {
8286					i = max;
8287
8288				} else {
8289					i = one ? index : 0;
8290				}
8291
8292				// Loop through all the selected options
8293				for ( ; i < max; i++ ) {
8294					option = options[ i ];
8295
8296					// Support: IE <=9 only
8297					// IE8-9 doesn't update selected after form reset (#2551)
8298					if ( ( option.selected || i === index ) &&
8299
8300							// Don't return options that are disabled or in a disabled optgroup
8301							!option.disabled &&
8302							( !option.parentNode.disabled ||
8303								!nodeName( option.parentNode, "optgroup" ) ) ) {
8304
8305						// Get the specific value for the option
8306						value = jQuery( option ).val();
8307
8308						// We don't need an array for one selects
8309						if ( one ) {
8310							return value;
8311						}
8312
8313						// Multi-Selects return an array
8314						values.push( value );
8315					}
8316				}
8317
8318				return values;
8319			},
8320
8321			set: function( elem, value ) {
8322				var optionSet, option,
8323					options = elem.options,
8324					values = jQuery.makeArray( value ),
8325					i = options.length;
8326
8327				while ( i-- ) {
8328					option = options[ i ];
8329
8330					/* eslint-disable no-cond-assign */
8331
8332					if ( option.selected =
8333						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
8334					) {
8335						optionSet = true;
8336					}
8337
8338					/* eslint-enable no-cond-assign */
8339				}
8340
8341				// Force browsers to behave consistently when non-matching value is set
8342				if ( !optionSet ) {
8343					elem.selectedIndex = -1;
8344				}
8345				return values;
8346			}
8347		}
8348	}
8349} );
8350
8351// Radios and checkboxes getter/setter
8352jQuery.each( [ "radio", "checkbox" ], function() {
8353	jQuery.valHooks[ this ] = {
8354		set: function( elem, value ) {
8355			if ( Array.isArray( value ) ) {
8356				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
8357			}
8358		}
8359	};
8360	if ( !support.checkOn ) {
8361		jQuery.valHooks[ this ].get = function( elem ) {
8362			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
8363		};
8364	}
8365} );
8366
8367
8368
8369
8370// Return jQuery for attributes-only inclusion
8371
8372
8373support.focusin = "onfocusin" in window;
8374
8375
8376var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
8377	stopPropagationCallback = function( e ) {
8378		e.stopPropagation();
8379	};
8380
8381jQuery.extend( jQuery.event, {
8382
8383	trigger: function( event, data, elem, onlyHandlers ) {
8384
8385		var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
8386			eventPath = [ elem || document ],
8387			type = hasOwn.call( event, "type" ) ? event.type : event,
8388			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
8389
8390		cur = lastElement = tmp = elem = elem || document;
8391
8392		// Don't do events on text and comment nodes
8393		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
8394			return;
8395		}
8396
8397		// focus/blur morphs to focusin/out; ensure we're not firing them right now
8398		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
8399			return;
8400		}
8401
8402		if ( type.indexOf( "." ) > -1 ) {
8403
8404			// Namespaced trigger; create a regexp to match event type in handle()
8405			namespaces = type.split( "." );
8406			type = namespaces.shift();
8407			namespaces.sort();
8408		}
8409		ontype = type.indexOf( ":" ) < 0 && "on" + type;
8410
8411		// Caller can pass in a jQuery.Event object, Object, or just an event type string
8412		event = event[ jQuery.expando ] ?
8413			event :
8414			new jQuery.Event( type, typeof event === "object" && event );
8415
8416		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
8417		event.isTrigger = onlyHandlers ? 2 : 3;
8418		event.namespace = namespaces.join( "." );
8419		event.rnamespace = event.namespace ?
8420			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
8421			null;
8422
8423		// Clean up the event in case it is being reused
8424		event.result = undefined;
8425		if ( !event.target ) {
8426			event.target = elem;
8427		}
8428
8429		// Clone any incoming data and prepend the event, creating the handler arg list
8430		data = data == null ?
8431			[ event ] :
8432			jQuery.makeArray( data, [ event ] );
8433
8434		// Allow special events to draw outside the lines
8435		special = jQuery.event.special[ type ] || {};
8436		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
8437			return;
8438		}
8439
8440		// Determine event propagation path in advance, per W3C events spec (#9951)
8441		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
8442		if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
8443
8444			bubbleType = special.delegateType || type;
8445			if ( !rfocusMorph.test( bubbleType + type ) ) {
8446				cur = cur.parentNode;
8447			}
8448			for ( ; cur; cur = cur.parentNode ) {
8449				eventPath.push( cur );
8450				tmp = cur;
8451			}
8452
8453			// Only add window if we got to document (e.g., not plain obj or detached DOM)
8454			if ( tmp === ( elem.ownerDocument || document ) ) {
8455				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
8456			}
8457		}
8458
8459		// Fire handlers on the event path
8460		i = 0;
8461		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
8462			lastElement = cur;
8463			event.type = i > 1 ?
8464				bubbleType :
8465				special.bindType || type;
8466
8467			// jQuery handler
8468			handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
8469				dataPriv.get( cur, "handle" );
8470			if ( handle ) {
8471				handle.apply( cur, data );
8472			}
8473
8474			// Native handler
8475			handle = ontype && cur[ ontype ];
8476			if ( handle && handle.apply && acceptData( cur ) ) {
8477				event.result = handle.apply( cur, data );
8478				if ( event.result === false ) {
8479					event.preventDefault();
8480				}
8481			}
8482		}
8483		event.type = type;
8484
8485		// If nobody prevented the default action, do it now
8486		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
8487
8488			if ( ( !special._default ||
8489				special._default.apply( eventPath.pop(), data ) === false ) &&
8490				acceptData( elem ) ) {
8491
8492				// Call a native DOM method on the target with the same name as the event.
8493				// Don't do default actions on window, that's where global variables be (#6170)
8494				if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
8495
8496					// Don't re-trigger an onFOO event when we call its FOO() method
8497					tmp = elem[ ontype ];
8498
8499					if ( tmp ) {
8500						elem[ ontype ] = null;
8501					}
8502
8503					// Prevent re-triggering of the same event, since we already bubbled it above
8504					jQuery.event.triggered = type;
8505
8506					if ( event.isPropagationStopped() ) {
8507						lastElement.addEventListener( type, stopPropagationCallback );
8508					}
8509
8510					elem[ type ]();
8511
8512					if ( event.isPropagationStopped() ) {
8513						lastElement.removeEventListener( type, stopPropagationCallback );
8514					}
8515
8516					jQuery.event.triggered = undefined;
8517
8518					if ( tmp ) {
8519						elem[ ontype ] = tmp;
8520					}
8521				}
8522			}
8523		}
8524
8525		return event.result;
8526	},
8527
8528	// Piggyback on a donor event to simulate a different one
8529	// Used only for `focus(in | out)` events
8530	simulate: function( type, elem, event ) {
8531		var e = jQuery.extend(
8532			new jQuery.Event(),
8533			event,
8534			{
8535				type: type,
8536				isSimulated: true
8537			}
8538		);
8539
8540		jQuery.event.trigger( e, null, elem );
8541	}
8542
8543} );
8544
8545jQuery.fn.extend( {
8546
8547	trigger: function( type, data ) {
8548		return this.each( function() {
8549			jQuery.event.trigger( type, data, this );
8550		} );
8551	},
8552	triggerHandler: function( type, data ) {
8553		var elem = this[ 0 ];
8554		if ( elem ) {
8555			return jQuery.event.trigger( type, data, elem, true );
8556		}
8557	}
8558} );
8559
8560
8561// Support: Firefox <=44
8562// Firefox doesn't have focus(in | out) events
8563// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
8564//
8565// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
8566// focus(in | out) events fire after focus & blur events,
8567// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
8568// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
8569if ( !support.focusin ) {
8570	jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
8571
8572		// Attach a single capturing handler on the document while someone wants focusin/focusout
8573		var handler = function( event ) {
8574			jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
8575		};
8576
8577		jQuery.event.special[ fix ] = {
8578			setup: function() {
8579				var doc = this.ownerDocument || this,
8580					attaches = dataPriv.access( doc, fix );
8581
8582				if ( !attaches ) {
8583					doc.addEventListener( orig, handler, true );
8584				}
8585				dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
8586			},
8587			teardown: function() {
8588				var doc = this.ownerDocument || this,
8589					attaches = dataPriv.access( doc, fix ) - 1;
8590
8591				if ( !attaches ) {
8592					doc.removeEventListener( orig, handler, true );
8593					dataPriv.remove( doc, fix );
8594
8595				} else {
8596					dataPriv.access( doc, fix, attaches );
8597				}
8598			}
8599		};
8600	} );
8601}
8602var location = window.location;
8603
8604var nonce = Date.now();
8605
8606var rquery = ( /\?/ );
8607
8608
8609
8610// Cross-browser xml parsing
8611jQuery.parseXML = function( data ) {
8612	var xml;
8613	if ( !data || typeof data !== "string" ) {
8614		return null;
8615	}
8616
8617	// Support: IE 9 - 11 only
8618	// IE throws on parseFromString with invalid input.
8619	try {
8620		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8621	} catch ( e ) {
8622		xml = undefined;
8623	}
8624
8625	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
8626		jQuery.error( "Invalid XML: " + data );
8627	}
8628	return xml;
8629};
8630
8631
8632var
8633	rbracket = /\[\]$/,
8634	rCRLF = /\r?\n/g,
8635	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8636	rsubmittable = /^(?:input|select|textarea|keygen)/i;
8637
8638function buildParams( prefix, obj, traditional, add ) {
8639	var name;
8640
8641	if ( Array.isArray( obj ) ) {
8642
8643		// Serialize array item.
8644		jQuery.each( obj, function( i, v ) {
8645			if ( traditional || rbracket.test( prefix ) ) {
8646
8647				// Treat each array item as a scalar.
8648				add( prefix, v );
8649
8650			} else {
8651
8652				// Item is non-scalar (array or object), encode its numeric index.
8653				buildParams(
8654					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
8655					v,
8656					traditional,
8657					add
8658				);
8659			}
8660		} );
8661
8662	} else if ( !traditional && toType( obj ) === "object" ) {
8663
8664		// Serialize object item.
8665		for ( name in obj ) {
8666			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8667		}
8668
8669	} else {
8670
8671		// Serialize scalar item.
8672		add( prefix, obj );
8673	}
8674}
8675
8676// Serialize an array of form elements or a set of
8677// key/values into a query string
8678jQuery.param = function( a, traditional ) {
8679	var prefix,
8680		s = [],
8681		add = function( key, valueOrFunction ) {
8682
8683			// If value is a function, invoke it and use its return value
8684			var value = isFunction( valueOrFunction ) ?
8685				valueOrFunction() :
8686				valueOrFunction;
8687
8688			s[ s.length ] = encodeURIComponent( key ) + "=" +
8689				encodeURIComponent( value == null ? "" : value );
8690		};
8691
8692	if ( a == null ) {
8693		return "";
8694	}
8695
8696	// If an array was passed in, assume that it is an array of form elements.
8697	if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8698
8699		// Serialize the form elements
8700		jQuery.each( a, function() {
8701			add( this.name, this.value );
8702		} );
8703
8704	} else {
8705
8706		// If traditional, encode the "old" way (the way 1.3.2 or older
8707		// did it), otherwise encode params recursively.
8708		for ( prefix in a ) {
8709			buildParams( prefix, a[ prefix ], traditional, add );
8710		}
8711	}
8712
8713	// Return the resulting serialization
8714	return s.join( "&" );
8715};
8716
8717jQuery.fn.extend( {
8718	serialize: function() {
8719		return jQuery.param( this.serializeArray() );
8720	},
8721	serializeArray: function() {
8722		return this.map( function() {
8723
8724			// Can add propHook for "elements" to filter or add form elements
8725			var elements = jQuery.prop( this, "elements" );
8726			return elements ? jQuery.makeArray( elements ) : this;
8727		} )
8728		.filter( function() {
8729			var type = this.type;
8730
8731			// Use .is( ":disabled" ) so that fieldset[disabled] works
8732			return this.name && !jQuery( this ).is( ":disabled" ) &&
8733				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8734				( this.checked || !rcheckableType.test( type ) );
8735		} )
8736		.map( function( i, elem ) {
8737			var val = jQuery( this ).val();
8738
8739			if ( val == null ) {
8740				return null;
8741			}
8742
8743			if ( Array.isArray( val ) ) {
8744				return jQuery.map( val, function( val ) {
8745					return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8746				} );
8747			}
8748
8749			return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8750		} ).get();
8751	}
8752} );
8753
8754
8755var
8756	r20 = /%20/g,
8757	rhash = /#.*$/,
8758	rantiCache = /([?&])_=[^&]*/,
8759	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
8760
8761	// #7653, #8125, #8152: local protocol detection
8762	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8763	rnoContent = /^(?:GET|HEAD)$/,
8764	rprotocol = /^\/\//,
8765
8766	/* Prefilters
8767	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8768	 * 2) These are called:
8769	 *    - BEFORE asking for a transport
8770	 *    - AFTER param serialization (s.data is a string if s.processData is true)
8771	 * 3) key is the dataType
8772	 * 4) the catchall symbol "*" can be used
8773	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8774	 */
8775	prefilters = {},
8776
8777	/* Transports bindings
8778	 * 1) key is the dataType
8779	 * 2) the catchall symbol "*" can be used
8780	 * 3) selection will start with transport dataType and THEN go to "*" if needed
8781	 */
8782	transports = {},
8783
8784	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8785	allTypes = "*/".concat( "*" ),
8786
8787	// Anchor tag for parsing the document origin
8788	originAnchor = document.createElement( "a" );
8789	originAnchor.href = location.href;
8790
8791// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8792function addToPrefiltersOrTransports( structure ) {
8793
8794	// dataTypeExpression is optional and defaults to "*"
8795	return function( dataTypeExpression, func ) {
8796
8797		if ( typeof dataTypeExpression !== "string" ) {
8798			func = dataTypeExpression;
8799			dataTypeExpression = "*";
8800		}
8801
8802		var dataType,
8803			i = 0,
8804			dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
8805
8806		if ( isFunction( func ) ) {
8807
8808			// For each dataType in the dataTypeExpression
8809			while ( ( dataType = dataTypes[ i++ ] ) ) {
8810
8811				// Prepend if requested
8812				if ( dataType[ 0 ] === "+" ) {
8813					dataType = dataType.slice( 1 ) || "*";
8814					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
8815
8816				// Otherwise append
8817				} else {
8818					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
8819				}
8820			}
8821		}
8822	};
8823}
8824
8825// Base inspection function for prefilters and transports
8826function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8827
8828	var inspected = {},
8829		seekingTransport = ( structure === transports );
8830
8831	function inspect( dataType ) {
8832		var selected;
8833		inspected[ dataType ] = true;
8834		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8835			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8836			if ( typeof dataTypeOrTransport === "string" &&
8837				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8838
8839				options.dataTypes.unshift( dataTypeOrTransport );
8840				inspect( dataTypeOrTransport );
8841				return false;
vendor: 10,690 bytes, lines 8842-9279
8842			} else if ( seekingTransport ) {
8843				return !( selected = dataTypeOrTransport );
8844			}
8845		} );
8846		return selected;
8847	}
8848
8849	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8850}
8851
8852// A special extend for ajax options
8853// that takes "flat" options (not to be deep extended)
8854// Fixes #9887
8855function ajaxExtend( target, src ) {
8856	var key, deep,
8857		flatOptions = jQuery.ajaxSettings.flatOptions || {};
8858
8859	for ( key in src ) {
8860		if ( src[ key ] !== undefined ) {
8861			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8862		}
8863	}
8864	if ( deep ) {
8865		jQuery.extend( true, target, deep );
8866	}
8867
8868	return target;
8869}
8870
8871/* Handles responses to an ajax request:
8872 * - finds the right dataType (mediates between content-type and expected dataType)
8873 * - returns the corresponding response
8874 */
8875function ajaxHandleResponses( s, jqXHR, responses ) {
8876
8877	var ct, type, finalDataType, firstDataType,
8878		contents = s.contents,
8879		dataTypes = s.dataTypes;
8880
8881	// Remove auto dataType and get content-type in the process
8882	while ( dataTypes[ 0 ] === "*" ) {
8883		dataTypes.shift();
8884		if ( ct === undefined ) {
8885			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
8886		}
8887	}
8888
8889	// Check if we're dealing with a known content-type
8890	if ( ct ) {
8891		for ( type in contents ) {
8892			if ( contents[ type ] && contents[ type ].test( ct ) ) {
8893				dataTypes.unshift( type );
8894				break;
8895			}
8896		}
8897	}
8898
8899	// Check to see if we have a response for the expected dataType
8900	if ( dataTypes[ 0 ] in responses ) {
8901		finalDataType = dataTypes[ 0 ];
8902	} else {
8903
8904		// Try convertible dataTypes
8905		for ( type in responses ) {
8906			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
8907				finalDataType = type;
8908				break;
8909			}
8910			if ( !firstDataType ) {
8911				firstDataType = type;
8912			}
8913		}
8914
8915		// Or just use first one
8916		finalDataType = finalDataType || firstDataType;
8917	}
8918
8919	// If we found a dataType
8920	// We add the dataType to the list if needed
8921	// and return the corresponding response
8922	if ( finalDataType ) {
8923		if ( finalDataType !== dataTypes[ 0 ] ) {
8924			dataTypes.unshift( finalDataType );
8925		}
8926		return responses[ finalDataType ];
8927	}
8928}
8929
8930/* Chain conversions given the request and the original response
8931 * Also sets the responseXXX fields on the jqXHR instance
8932 */
8933function ajaxConvert( s, response, jqXHR, isSuccess ) {
8934	var conv2, current, conv, tmp, prev,
8935		converters = {},
8936
8937		// Work with a copy of dataTypes in case we need to modify it for conversion
8938		dataTypes = s.dataTypes.slice();
8939
8940	// Create converters map with lowercased keys
8941	if ( dataTypes[ 1 ] ) {
8942		for ( conv in s.converters ) {
8943			converters[ conv.toLowerCase() ] = s.converters[ conv ];
8944		}
8945	}
8946
8947	current = dataTypes.shift();
8948
8949	// Convert to each sequential dataType
8950	while ( current ) {
8951
8952		if ( s.responseFields[ current ] ) {
8953			jqXHR[ s.responseFields[ current ] ] = response;
8954		}
8955
8956		// Apply the dataFilter if provided
8957		if ( !prev && isSuccess && s.dataFilter ) {
8958			response = s.dataFilter( response, s.dataType );
8959		}
8960
8961		prev = current;
8962		current = dataTypes.shift();
8963
8964		if ( current ) {
8965
8966			// There's only work to do if current dataType is non-auto
8967			if ( current === "*" ) {
8968
8969				current = prev;
8970
8971			// Convert response if prev dataType is non-auto and differs from current
8972			} else if ( prev !== "*" && prev !== current ) {
8973
8974				// Seek a direct converter
8975				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8976
8977				// If none found, seek a pair
8978				if ( !conv ) {
8979					for ( conv2 in converters ) {
8980
8981						// If conv2 outputs current
8982						tmp = conv2.split( " " );
8983						if ( tmp[ 1 ] === current ) {
8984
8985							// If prev can be converted to accepted input
8986							conv = converters[ prev + " " + tmp[ 0 ] ] ||
8987								converters[ "* " + tmp[ 0 ] ];
8988							if ( conv ) {
8989
8990								// Condense equivalence converters
8991								if ( conv === true ) {
8992									conv = converters[ conv2 ];
8993
8994								// Otherwise, insert the intermediate dataType
8995								} else if ( converters[ conv2 ] !== true ) {
8996									current = tmp[ 0 ];
8997									dataTypes.unshift( tmp[ 1 ] );
8998								}
8999								break;
9000							}
9001						}
9002					}
9003				}
9004
9005				// Apply converter (if not an equivalence)
9006				if ( conv !== true ) {
9007
9008					// Unless errors are allowed to bubble, catch and return them
9009					if ( conv && s.throws ) {
9010						response = conv( response );
9011					} else {
9012						try {
9013							response = conv( response );
9014						} catch ( e ) {
9015							return {
9016								state: "parsererror",
9017								error: conv ? e : "No conversion from " + prev + " to " + current
9018							};
9019						}
9020					}
9021				}
9022			}
9023		}
9024	}
9025
9026	return { state: "success", data: response };
9027}
9028
9029jQuery.extend( {
9030
9031	// Counter for holding the number of active queries
9032	active: 0,
9033
9034	// Last-Modified header cache for next request
9035	lastModified: {},
9036	etag: {},
9037
9038	ajaxSettings: {
9039		url: location.href,
9040		type: "GET",
9041		isLocal: rlocalProtocol.test( location.protocol ),
9042		global: true,
9043		processData: true,
9044		async: true,
9045		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
9046
9047		/*
9048		timeout: 0,
9049		data: null,
9050		dataType: null,
9051		username: null,
9052		password: null,
9053		cache: null,
9054		throws: false,
9055		traditional: false,
9056		headers: {},
9057		*/
9058
9059		accepts: {
9060			"*": allTypes,
9061			text: "text/plain",
9062			html: "text/html",
9063			xml: "application/xml, text/xml",
9064			json: "application/json, text/javascript"
9065		},
9066
9067		contents: {
9068			xml: /\bxml\b/,
9069			html: /\bhtml/,
9070			json: /\bjson\b/
9071		},
9072
9073		responseFields: {
9074			xml: "responseXML",
9075			text: "responseText",
9076			json: "responseJSON"
9077		},
9078
9079		// Data converters
9080		// Keys separate source (or catchall "*") and destination types with a single space
9081		converters: {
9082
9083			// Convert anything to text
9084			"* text": String,
9085
9086			// Text to html (true = no transformation)
9087			"text html": true,
9088
9089			// Evaluate text as a json expression
9090			"text json": JSON.parse,
9091
9092			// Parse text as xml
9093			"text xml": jQuery.parseXML
9094		},
9095
9096		// For options that shouldn't be deep extended:
9097		// you can add your own custom options here if
9098		// and when you create one that shouldn't be
9099		// deep extended (see ajaxExtend)
9100		flatOptions: {
9101			url: true,
9102			context: true
9103		}
9104	},
9105
9106	// Creates a full fledged settings object into target
9107	// with both ajaxSettings and settings fields.
9108	// If target is omitted, writes into ajaxSettings.
9109	ajaxSetup: function( target, settings ) {
9110		return settings ?
9111
9112			// Building a settings object
9113			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
9114
9115			// Extending ajaxSettings
9116			ajaxExtend( jQuery.ajaxSettings, target );
9117	},
9118
9119	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
9120	ajaxTransport: addToPrefiltersOrTransports( transports ),
9121
9122	// Main method
9123	ajax: function( url, options ) {
9124
9125		// If url is an object, simulate pre-1.5 signature
9126		if ( typeof url === "object" ) {
9127			options = url;
9128			url = undefined;
9129		}
9130
9131		// Force options to be an object
9132		options = options || {};
9133
9134		var transport,
9135
9136			// URL without anti-cache param
9137			cacheURL,
9138
9139			// Response headers
9140			responseHeadersString,
9141			responseHeaders,
9142
9143			// timeout handle
9144			timeoutTimer,
9145
9146			// Url cleanup var
9147			urlAnchor,
9148
9149			// Request state (becomes false upon send and true upon completion)
9150			completed,
9151
9152			// To know if global events are to be dispatched
9153			fireGlobals,
9154
9155			// Loop variable
9156			i,
9157
9158			// uncached part of the url
9159			uncached,
9160
9161			// Create the final options object
9162			s = jQuery.ajaxSetup( {}, options ),
9163
9164			// Callbacks context
9165			callbackContext = s.context || s,
9166
9167			// Context for global events is callbackContext if it is a DOM node or jQuery collection
9168			globalEventContext = s.context &&
9169				( callbackContext.nodeType || callbackContext.jquery ) ?
9170					jQuery( callbackContext ) :
9171					jQuery.event,
9172
9173			// Deferreds
9174			deferred = jQuery.Deferred(),
9175			completeDeferred = jQuery.Callbacks( "once memory" ),
9176
9177			// Status-dependent callbacks
9178			statusCode = s.statusCode || {},
9179
9180			// Headers (they are sent all at once)
9181			requestHeaders = {},
9182			requestHeadersNames = {},
9183
9184			// Default abort message
9185			strAbort = "canceled",
9186
9187			// Fake xhr
9188			jqXHR = {
9189				readyState: 0,
9190
9191				// Builds headers hashtable if needed
9192				getResponseHeader: function( key ) {
9193					var match;
9194					if ( completed ) {
9195						if ( !responseHeaders ) {
9196							responseHeaders = {};
9197							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
9198								responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
9199									( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
9200										.concat( match[ 2 ] );
9201							}
9202						}
9203						match = responseHeaders[ key.toLowerCase() + " " ];
9204					}
9205					return match == null ? null : match.join( ", " );
9206				},
9207
9208				// Raw string
9209				getAllResponseHeaders: function() {
9210					return completed ? responseHeadersString : null;
9211				},
9212
9213				// Caches the header
9214				setRequestHeader: function( name, value ) {
9215					if ( completed == null ) {
9216						name = requestHeadersNames[ name.toLowerCase() ] =
9217							requestHeadersNames[ name.toLowerCase() ] || name;
9218						requestHeaders[ name ] = value;
9219					}
9220					return this;
9221				},
9222
9223				// Overrides response content-type header
9224				overrideMimeType: function( type ) {
9225					if ( completed == null ) {
9226						s.mimeType = type;
9227					}
9228					return this;
9229				},
9230
9231				// Status-dependent callbacks
9232				statusCode: function( map ) {
9233					var code;
9234					if ( map ) {
9235						if ( completed ) {
9236
9237							// Execute the appropriate callbacks
9238							jqXHR.always( map[ jqXHR.status ] );
9239						} else {
9240
9241							// Lazy-add the new callbacks in a way that preserves old ones
9242							for ( code in map ) {
9243								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9244							}
9245						}
9246					}
9247					return this;
9248				},
9249
9250				// Cancel the request
9251				abort: function( statusText ) {
9252					var finalText = statusText || strAbort;
9253					if ( transport ) {
9254						transport.abort( finalText );
9255					}
9256					done( 0, finalText );
9257					return this;
9258				}
9259			};
9260
9261		// Attach deferreds
9262		deferred.promise( jqXHR );
9263
9264		// Add protocol if not provided (prefilters might expect it)
9265		// Handle falsy url in the settings object (#10093: consistency with old signature)
9266		// We also use the url parameter if available
9267		s.url = ( ( url || s.url || location.href ) + "" )
9268			.replace( rprotocol, location.protocol + "//" );
9269
9270		// Alias method option to type as per ticket #12004
9271		s.type = options.method || options.type || s.method || s.type;
9272
9273		// Extract dataTypes list
9274		s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
9275
9276		// A cross-domain request is in order when the origin doesn't match the current origin.
9277		if ( s.crossDomain == null ) {
9278			urlAnchor = document.createElement( "a" );
9279
vendor: 16,732 bytes, lines 9280-9934
9280			// Support: IE <=8 - 11, Edge 12 - 15
9281			// IE throws exception on accessing the href property if url is malformed,
9282			// e.g. http://example.com:80x/
9283			try {
9284				urlAnchor.href = s.url;
9285
9286				// Support: IE <=8 - 11 only
9287				// Anchor's host property isn't correctly set when s.url is relative
9288				urlAnchor.href = urlAnchor.href;
9289				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
9290					urlAnchor.protocol + "//" + urlAnchor.host;
9291			} catch ( e ) {
9292
9293				// If there is an error parsing the URL, assume it is crossDomain,
9294				// it can be rejected by the transport if it is invalid
9295				s.crossDomain = true;
9296			}
9297		}
9298
9299		// Convert data if not already a string
9300		if ( s.data && s.processData && typeof s.data !== "string" ) {
9301			s.data = jQuery.param( s.data, s.traditional );
9302		}
9303
9304		// Apply prefilters
9305		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9306
9307		// If request was aborted inside a prefilter, stop there
9308		if ( completed ) {
9309			return jqXHR;
9310		}
9311
9312		// We can fire global events as of now if asked to
9313		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
9314		fireGlobals = jQuery.event && s.global;
9315
9316		// Watch for a new set of requests
9317		if ( fireGlobals && jQuery.active++ === 0 ) {
9318			jQuery.event.trigger( "ajaxStart" );
9319		}
9320
9321		// Uppercase the type
9322		s.type = s.type.toUpperCase();
9323
9324		// Determine if request has content
9325		s.hasContent = !rnoContent.test( s.type );
9326
9327		// Save the URL in case we're toying with the If-Modified-Since
9328		// and/or If-None-Match header later on
9329		// Remove hash to simplify url manipulation
9330		cacheURL = s.url.replace( rhash, "" );
9331
9332		// More options handling for requests with no content
9333		if ( !s.hasContent ) {
9334
9335			// Remember the hash so we can put it back
9336			uncached = s.url.slice( cacheURL.length );
9337
9338			// If data is available and should be processed, append data to url
9339			if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
9340				cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
9341
9342				// #9682: remove data so that it's not used in an eventual retry
9343				delete s.data;
9344			}
9345
9346			// Add or update anti-cache param if needed
9347			if ( s.cache === false ) {
9348				cacheURL = cacheURL.replace( rantiCache, "$1" );
9349				uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
9350			}
9351
9352			// Put hash and anti-cache on the URL that will be requested (gh-1732)
9353			s.url = cacheURL + uncached;
9354
9355		// Change '%20' to '+' if this is encoded form body content (gh-2658)
9356		} else if ( s.data && s.processData &&
9357			( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
9358			s.data = s.data.replace( r20, "+" );
9359		}
9360
9361		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9362		if ( s.ifModified ) {
9363			if ( jQuery.lastModified[ cacheURL ] ) {
9364				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9365			}
9366			if ( jQuery.etag[ cacheURL ] ) {
9367				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9368			}
9369		}
9370
9371		// Set the correct header, if data is being sent
9372		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9373			jqXHR.setRequestHeader( "Content-Type", s.contentType );
9374		}
9375
9376		// Set the Accepts header for the server, depending on the dataType
9377		jqXHR.setRequestHeader(
9378			"Accept",
9379			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
9380				s.accepts[ s.dataTypes[ 0 ] ] +
9381					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9382				s.accepts[ "*" ]
9383		);
9384
9385		// Check for headers option
9386		for ( i in s.headers ) {
9387			jqXHR.setRequestHeader( i, s.headers[ i ] );
9388		}
9389
9390		// Allow custom headers/mimetypes and early abort
9391		if ( s.beforeSend &&
9392			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
9393
9394			// Abort if not done already and return
9395			return jqXHR.abort();
9396		}
9397
9398		// Aborting is no longer a cancellation
9399		strAbort = "abort";
9400
9401		// Install callbacks on deferreds
9402		completeDeferred.add( s.complete );
9403		jqXHR.done( s.success );
9404		jqXHR.fail( s.error );
9405
9406		// Get transport
9407		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9408
9409		// If no transport, we auto-abort
9410		if ( !transport ) {
9411			done( -1, "No Transport" );
9412		} else {
9413			jqXHR.readyState = 1;
9414
9415			// Send global event
9416			if ( fireGlobals ) {
9417				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9418			}
9419
9420			// If request was aborted inside ajaxSend, stop there
9421			if ( completed ) {
9422				return jqXHR;
9423			}
9424
9425			// Timeout
9426			if ( s.async && s.timeout > 0 ) {
9427				timeoutTimer = window.setTimeout( function() {
9428					jqXHR.abort( "timeout" );
9429				}, s.timeout );
9430			}
9431
9432			try {
9433				completed = false;
9434				transport.send( requestHeaders, done );
9435			} catch ( e ) {
9436
9437				// Rethrow post-completion exceptions
9438				if ( completed ) {
9439					throw e;
9440				}
9441
9442				// Propagate others as results
9443				done( -1, e );
9444			}
9445		}
9446
9447		// Callback for when everything is done
9448		function done( status, nativeStatusText, responses, headers ) {
9449			var isSuccess, success, error, response, modified,
9450				statusText = nativeStatusText;
9451
9452			// Ignore repeat invocations
9453			if ( completed ) {
9454				return;
9455			}
9456
9457			completed = true;
9458
9459			// Clear timeout if it exists
9460			if ( timeoutTimer ) {
9461				window.clearTimeout( timeoutTimer );
9462			}
9463
9464			// Dereference transport for early garbage collection
9465			// (no matter how long the jqXHR object will be used)
9466			transport = undefined;
9467
9468			// Cache response headers
9469			responseHeadersString = headers || "";
9470
9471			// Set readyState
9472			jqXHR.readyState = status > 0 ? 4 : 0;
9473
9474			// Determine if successful
9475			isSuccess = status >= 200 && status < 300 || status === 304;
9476
9477			// Get response data
9478			if ( responses ) {
9479				response = ajaxHandleResponses( s, jqXHR, responses );
9480			}
9481
9482			// Convert no matter what (that way responseXXX fields are always set)
9483			response = ajaxConvert( s, response, jqXHR, isSuccess );
9484
9485			// If successful, handle type chaining
9486			if ( isSuccess ) {
9487
9488				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9489				if ( s.ifModified ) {
9490					modified = jqXHR.getResponseHeader( "Last-Modified" );
9491					if ( modified ) {
9492						jQuery.lastModified[ cacheURL ] = modified;
9493					}
9494					modified = jqXHR.getResponseHeader( "etag" );
9495					if ( modified ) {
9496						jQuery.etag[ cacheURL ] = modified;
9497					}
9498				}
9499
9500				// if no content
9501				if ( status === 204 || s.type === "HEAD" ) {
9502					statusText = "nocontent";
9503
9504				// if not modified
9505				} else if ( status === 304 ) {
9506					statusText = "notmodified";
9507
9508				// If we have data, let's convert it
9509				} else {
9510					statusText = response.state;
9511					success = response.data;
9512					error = response.error;
9513					isSuccess = !error;
9514				}
9515			} else {
9516
9517				// Extract error from statusText and normalize for non-aborts
9518				error = statusText;
9519				if ( status || !statusText ) {
9520					statusText = "error";
9521					if ( status < 0 ) {
9522						status = 0;
9523					}
9524				}
9525			}
9526
9527			// Set data for the fake xhr object
9528			jqXHR.status = status;
9529			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9530
9531			// Success/Error
9532			if ( isSuccess ) {
9533				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9534			} else {
9535				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9536			}
9537
9538			// Status-dependent callbacks
9539			jqXHR.statusCode( statusCode );
9540			statusCode = undefined;
9541
9542			if ( fireGlobals ) {
9543				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9544					[ jqXHR, s, isSuccess ? success : error ] );
9545			}
9546
9547			// Complete
9548			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9549
9550			if ( fireGlobals ) {
9551				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9552
9553				// Handle the global AJAX counter
9554				if ( !( --jQuery.active ) ) {
9555					jQuery.event.trigger( "ajaxStop" );
9556				}
9557			}
9558		}
9559
9560		return jqXHR;
9561	},
9562
9563	getJSON: function( url, data, callback ) {
9564		return jQuery.get( url, data, callback, "json" );
9565	},
9566
9567	getScript: function( url, callback ) {
9568		return jQuery.get( url, undefined, callback, "script" );
9569	}
9570} );
9571
9572jQuery.each( [ "get", "post" ], function( i, method ) {
9573	jQuery[ method ] = function( url, data, callback, type ) {
9574
9575		// Shift arguments if data argument was omitted
9576		if ( isFunction( data ) ) {
9577			type = type || callback;
9578			callback = data;
9579			data = undefined;
9580		}
9581
9582		// The url can be an options object (which then must have .url)
9583		return jQuery.ajax( jQuery.extend( {
9584			url: url,
9585			type: method,
9586			dataType: type,
9587			data: data,
9588			success: callback
9589		}, jQuery.isPlainObject( url ) && url ) );
9590	};
9591} );
9592
9593
9594jQuery._evalUrl = function( url, options ) {
9595	return jQuery.ajax( {
9596		url: url,
9597
9598		// Make this explicit, since user can override this through ajaxSetup (#11264)
9599		type: "GET",
9600		dataType: "script",
9601		cache: true,
9602		async: false,
9603		global: false,
9604
9605		// Only evaluate the response if it is successful (gh-4126)
9606		// dataFilter is not invoked for failure responses, so using it instead
9607		// of the default converter is kludgy but it works.
9608		converters: {
9609			"text script": function() {}
9610		},
9611		dataFilter: function( response ) {
9612			jQuery.globalEval( response, options );
9613		}
9614	} );
9615};
9616
9617
9618jQuery.fn.extend( {
9619	wrapAll: function( html ) {
9620		var wrap;
9621
9622		if ( this[ 0 ] ) {
9623			if ( isFunction( html ) ) {
9624				html = html.call( this[ 0 ] );
9625			}
9626
9627			// The elements to wrap the target around
9628			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
9629
9630			if ( this[ 0 ].parentNode ) {
9631				wrap.insertBefore( this[ 0 ] );
9632			}
9633
9634			wrap.map( function() {
9635				var elem = this;
9636
9637				while ( elem.firstElementChild ) {
9638					elem = elem.firstElementChild;
9639				}
9640
9641				return elem;
9642			} ).append( this );
9643		}
9644
9645		return this;
9646	},
9647
9648	wrapInner: function( html ) {
9649		if ( isFunction( html ) ) {
9650			return this.each( function( i ) {
9651				jQuery( this ).wrapInner( html.call( this, i ) );
9652			} );
9653		}
9654
9655		return this.each( function() {
9656			var self = jQuery( this ),
9657				contents = self.contents();
9658
9659			if ( contents.length ) {
9660				contents.wrapAll( html );
9661
9662			} else {
9663				self.append( html );
9664			}
9665		} );
9666	},
9667
9668	wrap: function( html ) {
9669		var htmlIsFunction = isFunction( html );
9670
9671		return this.each( function( i ) {
9672			jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
9673		} );
9674	},
9675
9676	unwrap: function( selector ) {
9677		this.parent( selector ).not( "body" ).each( function() {
9678			jQuery( this ).replaceWith( this.childNodes );
9679		} );
9680		return this;
9681	}
9682} );
9683
9684
9685jQuery.expr.pseudos.hidden = function( elem ) {
9686	return !jQuery.expr.pseudos.visible( elem );
9687};
9688jQuery.expr.pseudos.visible = function( elem ) {
9689	return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
9690};
9691
9692
9693
9694
9695jQuery.ajaxSettings.xhr = function() {
9696	try {
9697		return new window.XMLHttpRequest();
9698	} catch ( e ) {}
9699};
9700
9701var xhrSuccessStatus = {
9702
9703		// File protocol always yields status code 0, assume 200
9704		0: 200,
9705
9706		// Support: IE <=9 only
9707		// #1450: sometimes IE returns 1223 when it should be 204
9708		1223: 204
9709	},
9710	xhrSupported = jQuery.ajaxSettings.xhr();
9711
9712support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9713support.ajax = xhrSupported = !!xhrSupported;
9714
9715jQuery.ajaxTransport( function( options ) {
9716	var callback, errorCallback;
9717
9718	// Cross domain only allowed if supported through XMLHttpRequest
9719	if ( support.cors || xhrSupported && !options.crossDomain ) {
9720		return {
9721			send: function( headers, complete ) {
9722				var i,
9723					xhr = options.xhr();
9724
9725				xhr.open(
9726					options.type,
9727					options.url,
9728					options.async,
9729					options.username,
9730					options.password
9731				);
9732
9733				// Apply custom fields if provided
9734				if ( options.xhrFields ) {
9735					for ( i in options.xhrFields ) {
9736						xhr[ i ] = options.xhrFields[ i ];
9737					}
9738				}
9739
9740				// Override mime type if needed
9741				if ( options.mimeType && xhr.overrideMimeType ) {
9742					xhr.overrideMimeType( options.mimeType );
9743				}
9744
9745				// X-Requested-With header
9746				// For cross-domain requests, seeing as conditions for a preflight are
9747				// akin to a jigsaw puzzle, we simply never set it to be sure.
9748				// (it can always be set on a per-request basis or even using ajaxSetup)
9749				// For same-domain requests, won't change header if already provided.
9750				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
9751					headers[ "X-Requested-With" ] = "XMLHttpRequest";
9752				}
9753
9754				// Set headers
9755				for ( i in headers ) {
9756					xhr.setRequestHeader( i, headers[ i ] );
9757				}
9758
9759				// Callback
9760				callback = function( type ) {
9761					return function() {
9762						if ( callback ) {
9763							callback = errorCallback = xhr.onload =
9764								xhr.onerror = xhr.onabort = xhr.ontimeout =
9765									xhr.onreadystatechange = null;
9766
9767							if ( type === "abort" ) {
9768								xhr.abort();
9769							} else if ( type === "error" ) {
9770
9771								// Support: IE <=9 only
9772								// On a manual native abort, IE9 throws
9773								// errors on any property access that is not readyState
9774								if ( typeof xhr.status !== "number" ) {
9775									complete( 0, "error" );
9776								} else {
9777									complete(
9778
9779										// File: protocol always yields status 0; see #8605, #14207
9780										xhr.status,
9781										xhr.statusText
9782									);
9783								}
9784							} else {
9785								complete(
9786									xhrSuccessStatus[ xhr.status ] || xhr.status,
9787									xhr.statusText,
9788
9789									// Support: IE <=9 only
9790									// IE9 has no XHR2 but throws on binary (trac-11426)
9791									// For XHR2 non-text, let the caller handle it (gh-2498)
9792									( xhr.responseType || "text" ) !== "text"  ||
9793									typeof xhr.responseText !== "string" ?
9794										{ binary: xhr.response } :
9795										{ text: xhr.responseText },
9796									xhr.getAllResponseHeaders()
9797								);
9798							}
9799						}
9800					};
9801				};
9802
9803				// Listen to events
9804				xhr.onload = callback();
9805				errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
9806
9807				// Support: IE 9 only
9808				// Use onreadystatechange to replace onabort
9809				// to handle uncaught aborts
9810				if ( xhr.onabort !== undefined ) {
9811					xhr.onabort = errorCallback;
9812				} else {
9813					xhr.onreadystatechange = function() {
9814
9815						// Check readyState before timeout as it changes
9816						if ( xhr.readyState === 4 ) {
9817
9818							// Allow onerror to be called first,
9819							// but that will not handle a native abort
9820							// Also, save errorCallback to a variable
9821							// as xhr.onerror cannot be accessed
9822							window.setTimeout( function() {
9823								if ( callback ) {
9824									errorCallback();
9825								}
9826							} );
9827						}
9828					};
9829				}
9830
9831				// Create the abort callback
9832				callback = callback( "abort" );
9833
9834				try {
9835
9836					// Do send the request (this may raise an exception)
9837					xhr.send( options.hasContent && options.data || null );
9838				} catch ( e ) {
9839
9840					// #14683: Only rethrow if this hasn't been notified as an error yet
9841					if ( callback ) {
9842						throw e;
9843					}
9844				}
9845			},
9846
9847			abort: function() {
9848				if ( callback ) {
9849					callback();
9850				}
9851			}
9852		};
9853	}
9854} );
9855
9856
9857
9858
9859// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
9860jQuery.ajaxPrefilter( function( s ) {
9861	if ( s.crossDomain ) {
9862		s.contents.script = false;
9863	}
9864} );
9865
9866// Install script dataType
9867jQuery.ajaxSetup( {
9868	accepts: {
9869		script: "text/javascript, application/javascript, " +
9870			"application/ecmascript, application/x-ecmascript"
9871	},
9872	contents: {
9873		script: /\b(?:java|ecma)script\b/
9874	},
9875	converters: {
9876		"text script": function( text ) {
9877			jQuery.globalEval( text );
9878			return text;
9879		}
9880	}
9881} );
9882
9883// Handle cache's special case and crossDomain
9884jQuery.ajaxPrefilter( "script", function( s ) {
9885	if ( s.cache === undefined ) {
9886		s.cache = false;
9887	}
9888	if ( s.crossDomain ) {
9889		s.type = "GET";
9890	}
9891} );
9892
9893// Bind script tag hack transport
9894jQuery.ajaxTransport( "script", function( s ) {
9895
9896	// This transport only deals with cross domain or forced-by-attrs requests
9897	if ( s.crossDomain || s.scriptAttrs ) {
9898		var script, callback;
9899		return {
9900			send: function( _, complete ) {
9901				script = jQuery( "<script>" )
9902					.attr( s.scriptAttrs || {} )
9903					.prop( { charset: s.scriptCharset, src: s.url } )
9904					.on( "load error", callback = function( evt ) {
9905						script.remove();
9906						callback = null;
9907						if ( evt ) {
9908							complete( evt.type === "error" ? 404 : 200, evt.type );
9909						}
9910					} );
9911
9912				// Use native DOM manipulation to avoid our domManip AJAX trickery
9913				document.head.appendChild( script[ 0 ] );
9914			},
9915			abort: function() {
9916				if ( callback ) {
9917					callback();
9918				}
9919			}
9920		};
9921	}
9922} );
9923
9924
9925
9926
9927var oldCallbacks = [],
9928	rjsonp = /(=)\?(?=&|$)|\?\?/;
9929
9930// Default jsonp settings
9931jQuery.ajaxSetup( {
9932	jsonp: "callback",
9933	jsonpCallback: function() {
9934		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce
vendor: 5,879 bytes, lines 9934-10150
9934++ ) );
9935		this[ callback ] = true;
9936		return callback;
9937	}
9938} );
9939
9940// Detect, normalize options and install callbacks for jsonp requests
9941jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9942
9943	var callbackName, overwritten, responseContainer,
9944		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9945			"url" :
9946			typeof s.data === "string" &&
9947				( s.contentType || "" )
9948					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
9949				rjsonp.test( s.data ) && "data"
9950		);
9951
9952	// Handle iff the expected data type is "jsonp" or we have a parameter to set
9953	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9954
9955		// Get callback name, remembering preexisting value associated with it
9956		callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
9957			s.jsonpCallback() :
9958			s.jsonpCallback;
9959
9960		// Insert callback into url or form data
9961		if ( jsonProp ) {
9962			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9963		} else if ( s.jsonp !== false ) {
9964			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9965		}
9966
9967		// Use data converter to retrieve json after script execution
9968		s.converters[ "script json" ] = function() {
9969			if ( !responseContainer ) {
9970				jQuery.error( callbackName + " was not called" );
9971			}
9972			return responseContainer[ 0 ];
9973		};
9974
9975		// Force json dataType
9976		s.dataTypes[ 0 ] = "json";
9977
9978		// Install callback
9979		overwritten = window[ callbackName ];
9980		window[ callbackName ] = function() {
9981			responseContainer = arguments;
9982		};
9983
9984		// Clean-up function (fires after converters)
9985		jqXHR.always( function() {
9986
9987			// If previous value didn't exist - remove it
9988			if ( overwritten === undefined ) {
9989				jQuery( window ).removeProp( callbackName );
9990
9991			// Otherwise restore preexisting value
9992			} else {
9993				window[ callbackName ] = overwritten;
9994			}
9995
9996			// Save back as free
9997			if ( s[ callbackName ] ) {
9998
9999				// Make sure that re-using the options doesn't screw things around
10000				s.jsonpCallback = originalSettings.jsonpCallback;
10001
10002				// Save the callback name for future use
10003				oldCallbacks.push( callbackName );
10004			}
10005
10006			// Call if it was a function and we have a response
10007			if ( responseContainer && isFunction( overwritten ) ) {
10008				overwritten( responseContainer[ 0 ] );
10009			}
10010
10011			responseContainer = overwritten = undefined;
10012		} );
10013
10014		// Delegate to script
10015		return "script";
10016	}
10017} );
10018
10019
10020
10021
10022// Support: Safari 8 only
10023// In Safari 8 documents created via document.implementation.createHTMLDocument
10024// collapse sibling forms: the second one becomes a child of the first one.
10025// Because of that, this security measure has to be disabled in Safari 8.
10026// https://bugs.webkit.org/show_bug.cgi?id=137337
10027support.createHTMLDocument = ( function() {
10028	var body = document.implementation.createHTMLDocument( "" ).body;
10029	body.innerHTML = "<form></form><form></form>";
10030	return body.childNodes.length === 2;
10031} )();
10032
10033
10034// Argument "data" should be string of html
10035// context (optional): If specified, the fragment will be created in this context,
10036// defaults to document
10037// keepScripts (optional): If true, will include scripts passed in the html string
10038jQuery.parseHTML = function( data, context, keepScripts ) {
10039	if ( typeof data !== "string" ) {
10040		return [];
10041	}
10042	if ( typeof context === "boolean" ) {
10043		keepScripts = context;
10044		context = false;
10045	}
10046
10047	var base, parsed, scripts;
10048
10049	if ( !context ) {
10050
10051		// Stop scripts or inline event handlers from being executed immediately
10052		// by using document.implementation
10053		if ( support.createHTMLDocument ) {
10054			context = document.implementation.createHTMLDocument( "" );
10055
10056			// Set the base href for the created document
10057			// so any parsed elements with URLs
10058			// are based on the document's URL (gh-2965)
10059			base = context.createElement( "base" );
10060			base.href = document.location.href;
10061			context.head.appendChild( base );
10062		} else {
10063			context = document;
10064		}
10065	}
10066
10067	parsed = rsingleTag.exec( data );
10068	scripts = !keepScripts && [];
10069
10070	// Single tag
10071	if ( parsed ) {
10072		return [ context.createElement( parsed[ 1 ] ) ];
10073	}
10074
10075	parsed = buildFragment( [ data ], context, scripts );
10076
10077	if ( scripts && scripts.length ) {
10078		jQuery( scripts ).remove();
10079	}
10080
10081	return jQuery.merge( [], parsed.childNodes );
10082};
10083
10084
10085/**
10086 * Load a url into a page
10087 */
10088jQuery.fn.load = function( url, params, callback ) {
10089	var selector, type, response,
10090		self = this,
10091		off = url.indexOf( " " );
10092
10093	if ( off > -1 ) {
10094		selector = stripAndCollapse( url.slice( off ) );
10095		url = url.slice( 0, off );
10096	}
10097
10098	// If it's a function
10099	if ( isFunction( params ) ) {
10100
10101		// We assume that it's the callback
10102		callback = params;
10103		params = undefined;
10104
10105	// Otherwise, build a param string
10106	} else if ( params && typeof params === "object" ) {
10107		type = "POST";
10108	}
10109
10110	// If we have elements to modify, make the request
10111	if ( self.length > 0 ) {
10112		jQuery.ajax( {
10113			url: url,
10114
10115			// If "type" variable is undefined, then "GET" method will be used.
10116			// Make value of this field explicit since
10117			// user can override it through ajaxSetup method
10118			type: type || "GET",
10119			dataType: "html",
10120			data: params
10121		} ).done( function( responseText ) {
10122
10123			// Save response for use in complete callback
10124			response = arguments;
10125
10126			self.html( selector ?
10127
10128				// If a selector was specified, locate the right elements in a dummy div
10129				// Exclude scripts to avoid IE 'Permission Denied' errors
10130				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
10131
10132				// Otherwise use the full result
10133				responseText );
10134
10135		// If the request succeeds, this function gets "data", "status", "jqXHR"
10136		// but they are ignored because response was set above.
10137		// If it fails, this function gets "jqXHR", "status", "error"
10138		} ).always( callback && function( jqXHR, status ) {
10139			self.each( function() {
10140				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
10141			} );
10142		} );
10143	}
10144
10145	return this;
10146};
10147
10148
10149
10150
vendor: 11,997 bytes, lines 10151-10555
10151// Attach a bunch of functions for handling common AJAX events
10152jQuery.each( [
10153	"ajaxStart",
10154	"ajaxStop",
10155	"ajaxComplete",
10156	"ajaxError",
10157	"ajaxSuccess",
10158	"ajaxSend"
10159], function( i, type ) {
10160	jQuery.fn[ type ] = function( fn ) {
10161		return this.on( type, fn );
10162	};
10163} );
10164
10165
10166
10167
10168jQuery.expr.pseudos.animated = function( elem ) {
10169	return jQuery.grep( jQuery.timers, function( fn ) {
10170		return elem === fn.elem;
10171	} ).length;
10172};
10173
10174
10175
10176
10177jQuery.offset = {
10178	setOffset: function( elem, options, i ) {
10179		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10180			position = jQuery.css( elem, "position" ),
10181			curElem = jQuery( elem ),
10182			props = {};
10183
10184		// Set position first, in-case top/left are set even on static elem
10185		if ( position === "static" ) {
10186			elem.style.position = "relative";
10187		}
10188
10189		curOffset = curElem.offset();
10190		curCSSTop = jQuery.css( elem, "top" );
10191		curCSSLeft = jQuery.css( elem, "left" );
10192		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10193			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
10194
10195		// Need to be able to calculate position if either
10196		// top or left is auto and position is either absolute or fixed
10197		if ( calculatePosition ) {
10198			curPosition = curElem.position();
10199			curTop = curPosition.top;
10200			curLeft = curPosition.left;
10201
10202		} else {
10203			curTop = parseFloat( curCSSTop ) || 0;
10204			curLeft = parseFloat( curCSSLeft ) || 0;
10205		}
10206
10207		if ( isFunction( options ) ) {
10208
10209			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
10210			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
10211		}
10212
10213		if ( options.top != null ) {
10214			props.top = ( options.top - curOffset.top ) + curTop;
10215		}
10216		if ( options.left != null ) {
10217			props.left = ( options.left - curOffset.left ) + curLeft;
10218		}
10219
10220		if ( "using" in options ) {
10221			options.using.call( elem, props );
10222
10223		} else {
10224			curElem.css( props );
10225		}
10226	}
10227};
10228
10229jQuery.fn.extend( {
10230
10231	// offset() relates an element's border box to the document origin
10232	offset: function( options ) {
10233
10234		// Preserve chaining for setter
10235		if ( arguments.length ) {
10236			return options === undefined ?
10237				this :
10238				this.each( function( i ) {
10239					jQuery.offset.setOffset( this, options, i );
10240				} );
10241		}
10242
10243		var rect, win,
10244			elem = this[ 0 ];
10245
10246		if ( !elem ) {
10247			return;
10248		}
10249
10250		// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
10251		// Support: IE <=11 only
10252		// Running getBoundingClientRect on a
10253		// disconnected node in IE throws an error
10254		if ( !elem.getClientRects().length ) {
10255			return { top: 0, left: 0 };
10256		}
10257
10258		// Get document-relative position by adding viewport scroll to viewport-relative gBCR
10259		rect = elem.getBoundingClientRect();
10260		win = elem.ownerDocument.defaultView;
10261		return {
10262			top: rect.top + win.pageYOffset,
10263			left: rect.left + win.pageXOffset
10264		};
10265	},
10266
10267	// position() relates an element's margin box to its offset parent's padding box
10268	// This corresponds to the behavior of CSS absolute positioning
10269	position: function() {
10270		if ( !this[ 0 ] ) {
10271			return;
10272		}
10273
10274		var offsetParent, offset, doc,
10275			elem = this[ 0 ],
10276			parentOffset = { top: 0, left: 0 };
10277
10278		// position:fixed elements are offset from the viewport, which itself always has zero offset
10279		if ( jQuery.css( elem, "position" ) === "fixed" ) {
10280
10281			// Assume position:fixed implies availability of getBoundingClientRect
10282			offset = elem.getBoundingClientRect();
10283
10284		} else {
10285			offset = this.offset();
10286
10287			// Account for the *real* offset parent, which can be the document or its root element
10288			// when a statically positioned element is identified
10289			doc = elem.ownerDocument;
10290			offsetParent = elem.offsetParent || doc.documentElement;
10291			while ( offsetParent &&
10292				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
10293				jQuery.css( offsetParent, "position" ) === "static" ) {
10294
10295				offsetParent = offsetParent.parentNode;
10296			}
10297			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
10298
10299				// Incorporate borders into its offset, since they are outside its content origin
10300				parentOffset = jQuery( offsetParent ).offset();
10301				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
10302				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
10303			}
10304		}
10305
10306		// Subtract parent offsets and element margins
10307		return {
10308			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10309			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
10310		};
10311	},
10312
10313	// This method will return documentElement in the following cases:
10314	// 1) For the element inside the iframe without offsetParent, this method will return
10315	//    documentElement of the parent window
10316	// 2) For the hidden or detached element
10317	// 3) For body or html element, i.e. in case of the html node - it will return itself
10318	//
10319	// but those exceptions were never presented as a real life use-cases
10320	// and might be considered as more preferable results.
10321	//
10322	// This logic, however, is not guaranteed and can change at any point in the future
10323	offsetParent: function() {
10324		return this.map( function() {
10325			var offsetParent = this.offsetParent;
10326
10327			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
10328				offsetParent = offsetParent.offsetParent;
10329			}
10330
10331			return offsetParent || documentElement;
10332		} );
10333	}
10334} );
10335
10336// Create scrollLeft and scrollTop methods
10337jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10338	var top = "pageYOffset" === prop;
10339
10340	jQuery.fn[ method ] = function( val ) {
10341		return access( this, function( elem, method, val ) {
10342
10343			// Coalesce documents and windows
10344			var win;
10345			if ( isWindow( elem ) ) {
10346				win = elem;
10347			} else if ( elem.nodeType === 9 ) {
10348				win = elem.defaultView;
10349			}
10350
10351			if ( val === undefined ) {
10352				return win ? win[ prop ] : elem[ method ];
10353			}
10354
10355			if ( win ) {
10356				win.scrollTo(
10357					!top ? val : win.pageXOffset,
10358					top ? val : win.pageYOffset
10359				);
10360
10361			} else {
10362				elem[ method ] = val;
10363			}
10364		}, method, val, arguments.length );
10365	};
10366} );
10367
10368// Support: Safari <=7 - 9.1, Chrome <=37 - 49
10369// Add the top/left cssHooks using jQuery.fn.position
10370// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10371// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
10372// getComputedStyle returns percent when specified for top/left/bottom/right;
10373// rather than make the css module depend on the offset module, just check for it here
10374jQuery.each( [ "top", "left" ], function( i, prop ) {
10375	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10376		function( elem, computed ) {
10377			if ( computed ) {
10378				computed = curCSS( elem, prop );
10379
10380				// If curCSS returns percentage, fallback to offset
10381				return rnumnonpx.test( computed ) ?
10382					jQuery( elem ).position()[ prop ] + "px" :
10383					computed;
10384			}
10385		}
10386	);
10387} );
10388
10389
10390// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10391jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10392	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
10393		function( defaultExtra, funcName ) {
10394
10395		// Margin is only for outerHeight, outerWidth
10396		jQuery.fn[ funcName ] = function( margin, value ) {
10397			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10398				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10399
10400			return access( this, function( elem, type, value ) {
10401				var doc;
10402
10403				if ( isWindow( elem ) ) {
10404
10405					// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
10406					return funcName.indexOf( "outer" ) === 0 ?
10407						elem[ "inner" + name ] :
10408						elem.document.documentElement[ "client" + name ];
10409				}
10410
10411				// Get document width or height
10412				if ( elem.nodeType === 9 ) {
10413					doc = elem.documentElement;
10414
10415					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
10416					// whichever is greatest
10417					return Math.max(
10418						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10419						elem.body[ "offset" + name ], doc[ "offset" + name ],
10420						doc[ "client" + name ]
10421					);
10422				}
10423
10424				return value === undefined ?
10425
10426					// Get width or height on the element, requesting but not forcing parseFloat
10427					jQuery.css( elem, type, extra ) :
10428
10429					// Set width or height on the element
10430					jQuery.style( elem, type, value, extra );
10431			}, type, chainable ? margin : undefined, chainable );
10432		};
10433	} );
10434} );
10435
10436
10437jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
10438	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10439	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
10440	function( i, name ) {
10441
10442	// Handle event binding
10443	jQuery.fn[ name ] = function( data, fn ) {
10444		return arguments.length > 0 ?
10445			this.on( name, null, data, fn ) :
10446			this.trigger( name );
10447	};
10448} );
10449
10450jQuery.fn.extend( {
10451	hover: function( fnOver, fnOut ) {
10452		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
10453	}
10454} );
10455
10456
10457
10458
10459jQuery.fn.extend( {
10460
10461	bind: function( types, data, fn ) {
10462		return this.on( types, null, data, fn );
10463	},
10464	unbind: function( types, fn ) {
10465		return this.off( types, null, fn );
10466	},
10467
10468	delegate: function( selector, types, data, fn ) {
10469		return this.on( types, selector, data, fn );
10470	},
10471	undelegate: function( selector, types, fn ) {
10472
10473		// ( namespace ) or ( selector, types [, fn] )
10474		return arguments.length === 1 ?
10475			this.off( selector, "**" ) :
10476			this.off( types, selector || "**", fn );
10477	}
10478} );
10479
10480// Bind a function to a context, optionally partially applying any
10481// arguments.
10482// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
10483// However, it is not slated for removal any time soon
10484jQuery.proxy = function( fn, context ) {
10485	var tmp, args, proxy;
10486
10487	if ( typeof context === "string" ) {
10488		tmp = fn[ context ];
10489		context = fn;
10490		fn = tmp;
10491	}
10492
10493	// Quick check to determine if target is callable, in the spec
10494	// this throws a TypeError, but we will just return undefined.
10495	if ( !isFunction( fn ) ) {
10496		return undefined;
10497	}
10498
10499	// Simulated bind
10500	args = slice.call( arguments, 2 );
10501	proxy = function() {
10502		return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
10503	};
10504
10505	// Set the guid of unique handler to the same of original handler, so it can be removed
10506	proxy.guid = fn.guid = fn.guid || jQuery.guid++;
10507
10508	return proxy;
10509};
10510
10511jQuery.holdReady = function( hold ) {
10512	if ( hold ) {
10513		jQuery.readyWait++;
10514	} else {
10515		jQuery.ready( true );
10516	}
10517};
10518jQuery.isArray = Array.isArray;
10519jQuery.parseJSON = JSON.parse;
10520jQuery.nodeName = nodeName;
10521jQuery.isFunction = isFunction;
10522jQuery.isWindow = isWindow;
10523jQuery.camelCase = camelCase;
10524jQuery.type = toType;
10525
10526jQuery.now = Date.now;
10527
10528jQuery.isNumeric = function( obj ) {
10529
10530	// As of jQuery 3.0, isNumeric is limited to
10531	// strings and numbers (primitives or objects)
10532	// that can be coerced to finite numbers (gh-2662)
10533	var type = jQuery.type( obj );
10534	return ( type === "number" || type === "string" ) &&
10535
10536		// parseFloat NaNs numeric-cast false positives ("")
10537		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
10538		// subtraction forces infinities to NaN
10539		!isNaN( obj - parseFloat( obj ) );
10540};
10541
10542
10543
10544
10545// Register as a named AMD module, since jQuery can be concatenated with other
10546// files that may use define, but not via a proper concatenation script that
10547// understands anonymous AMD modules. A named AMD is safest and most robust
10548// way to register. Lowercase jquery is used because AMD module names are
10549// derived from file names, and jQuery is normally delivered in a lowercase
10550// file name. Do this after creating the global so that if an AMD module wants
10551// to call noConflict to hide this version of jQuery, it will work.
10552
10553// Note that for maximum portability, libraries that are not jQuery should
10554// declare themselves as anonymous modules, and avoid setting a global if an
10555// AMD loader is present. jQuery is a special case. For more information, see
vendor: 5,435 bytes, lines 10556-10757
10556// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10557
10558if ( typeof define === "function" && define.amd ) {
10559	define( "jquery", [], function() {
10560		return jQuery;
10561	} );
10562}
10563
10564
10565
10566
10567var
10568
10569	// Map over jQuery in case of overwrite
10570	_jQuery = window.jQuery,
10571
10572	// Map over the $ in case of overwrite
10573	_$ = window.$;
10574
10575jQuery.noConflict = function( deep ) {
10576	if ( window.$ === jQuery ) {
10577		window.$ = _$;
10578	}
10579
10580	if ( deep && window.jQuery === jQuery ) {
10581		window.jQuery = _jQuery;
10582	}
10583
10584	return jQuery;
10585};
10586
10587// Expose jQuery and $ identifiers, even in AMD
10588// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10589// and CommonJS for browser emulators (#13566)
10590if ( !noGlobal ) {
10591	window.jQuery = window.$ = jQuery;
10592}
10593
10594
10595
10596
10597return jQuery;
10598} );
10599
10600/**!
10601 * @fileOverview Kickass library to create and place poppers near their reference elements.
10602 * @version 1.15.0
10603 * @license
10604 * Copyright (c) 2016 Federico Zivolo and contributors
10605 *
10606 * Permission is hereby granted, free of charge, to any person obtaining a copy
10607 * of this software and associated documentation files (the "Software"), to deal
10608 * in the Software without restriction, including without limitation the rights
10609 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10610 * copies of the Software, and to permit persons to whom the Software is
10611 * furnished to do so, subject to the following conditions:
10612 *
10613 * The above copyright notice and this permission notice shall be included in all
10614 * copies or substantial portions of the Software.
10615 *
10616 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10617 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10618 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10619 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
10620 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
10621 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
10622 * SOFTWARE.
10623 */
10624(function (global, factory) {
10625	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
10626	typeof define === 'function' && define.amd ? define(factory) :
10627	(global.Popper = factory());
10628}(this, (function () { 'use strict';
10629
10630var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
10631
10632var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
10633var timeoutDuration = 0;
10634for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
10635  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
10636    timeoutDuration = 1;
10637    break;
10638  }
10639}
10640
10641function microtaskDebounce(fn) {
10642  var called = false;
10643  return function () {
10644    if (called) {
10645      return;
10646    }
10647    called = true;
10648    window.Promise.resolve().then(function () {
10649      called = false;
10650      fn();
10651    });
10652  };
10653}
10654
10655function taskDebounce(fn) {
10656  var scheduled = false;
10657  return function () {
10658    if (!scheduled) {
10659      scheduled = true;
10660      setTimeout(function () {
10661        scheduled = false;
10662        fn();
10663      }, timeoutDuration);
10664    }
10665  };
10666}
10667
10668var supportsMicroTasks = isBrowser && window.Promise;
10669
10670/**
10671* Create a debounced version of a method, that's asynchronously deferred
10672* but called in the minimum time possible.
10673*
10674* @method
10675* @memberof Popper.Utils
10676* @argument {Function} fn
10677* @returns {Function}
10678*/
10679var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
10680
10681/**
10682 * Check if the given variable is a function
10683 * @method
10684 * @memberof Popper.Utils
10685 * @argument {Any} functionToCheck - variable to check
10686 * @returns {Boolean} answer to: is a function?
10687 */
10688function isFunction(functionToCheck) {
10689  var getType = {};
10690  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
10691}
10692
10693/**
10694 * Get CSS computed property of the given element
10695 * @method
10696 * @memberof Popper.Utils
10697 * @argument {Eement} element
10698 * @argument {String} property
10699 */
10700function getStyleComputedProperty(element, property) {
10701  if (element.nodeType !== 1) {
10702    return [];
10703  }
10704  // NOTE: 1 DOM access here
10705  var window = element.ownerDocument.defaultView;
10706  var css = window.getComputedStyle(element, null);
10707  return property ? css[property] : css;
10708}
10709
10710/**
10711 * Returns the parentNode or the host of the element
10712 * @method
10713 * @memberof Popper.Utils
10714 * @argument {Element} element
10715 * @returns {Element} parent
10716 */
10717function getParentNode(element) {
10718  if (element.nodeName === 'HTML') {
10719    return element;
10720  }
10721  return element.parentNode || element.host;
10722}
10723
10724/**
10725 * Returns the scrolling parent of the given element
10726 * @method
10727 * @memberof Popper.Utils
10728 * @argument {Element} element
10729 * @returns {Element} scroll parent
10730 */
10731function getScrollParent(element) {
10732  // Return body, `getScroll` will take care to get the correct `scrollTop` from it
10733  if (!element) {
10734    return document.body;
10735  }
10736
10737  switch (element.nodeName) {
10738    case 'HTML':
10739    case 'BODY':
10740      return element.ownerDocument.body;
10741    case '#document':
10742      return element.body;
10743  }
10744
10745  // Firefox want us to check `-x` and `-y` variations as well
10746
10747  var _getStyleComputedProp = getStyleComputedProperty(element),
10748      overflow = _getStyleComputedProp.overflow,
10749      overflowX = _getStyleComputedProp.overflowX,
10750      overflowY = _getStyleComputedProp.overflowY;
10751
10752  if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
10753    return element;
10754  }
10755
10756  return getScrollParent(getParentNode(element));
10757}
vendor: 5,677 bytes, lines 10757-10942
10757
10758
10759var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
10760var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
10761
10762/**
10763 * Determines if the browser is Internet Explorer
10764 * @method
10765 * @memberof Popper.Utils
10766 * @param {Number} version to check
10767 * @returns {Boolean} isIE
10768 */
10769function isIE(version) {
10770  if (version === 11) {
10771    return isIE11;
10772  }
10773  if (version === 10) {
10774    return isIE10;
10775  }
10776  return isIE11 || isIE10;
10777}
10778
10779/**
10780 * Returns the offset parent of the given element
10781 * @method
10782 * @memberof Popper.Utils
10783 * @argument {Element} element
10784 * @returns {Element} offset parent
10785 */
10786function getOffsetParent(element) {
10787  if (!element) {
10788    return document.documentElement;
10789  }
10790
10791  var noOffsetParent = isIE(10) ? document.body : null;
10792
10793  // NOTE: 1 DOM access here
10794  var offsetParent = element.offsetParent || null;
10795  // Skip hidden elements which don't have an offsetParent
10796  while (offsetParent === noOffsetParent && element.nextElementSibling) {
10797    offsetParent = (element = element.nextElementSibling).offsetParent;
10798  }
10799
10800  var nodeName = offsetParent && offsetParent.nodeName;
10801
10802  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
10803    return element ? element.ownerDocument.documentElement : document.documentElement;
10804  }
10805
10806  // .offsetParent will return the closest TH, TD or TABLE in case
10807  // no offsetParent is present, I hate this job...
10808  if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
10809    return getOffsetParent(offsetParent);
10810  }
10811
10812  return offsetParent;
10813}
10814
10815function isOffsetContainer(element) {
10816  var nodeName = element.nodeName;
10817
10818  if (nodeName === 'BODY') {
10819    return false;
10820  }
10821  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
10822}
10823
10824/**
10825 * Finds the root node (document, shadowDOM root) of the given element
10826 * @method
10827 * @memberof Popper.Utils
10828 * @argument {Element} node
10829 * @returns {Element} root node
10830 */
10831function getRoot(node) {
10832  if (node.parentNode !== null) {
10833    return getRoot(node.parentNode);
10834  }
10835
10836  return node;
10837}
10838
10839/**
10840 * Finds the offset parent common to the two provided nodes
10841 * @method
10842 * @memberof Popper.Utils
10843 * @argument {Element} element1
10844 * @argument {Element} element2
10845 * @returns {Element} common offset parent
10846 */
10847function findCommonOffsetParent(element1, element2) {
10848  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
10849  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
10850    return document.documentElement;
10851  }
10852
10853  // Here we make sure to give as "start" the element that comes first in the DOM
10854  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
10855  var start = order ? element1 : element2;
10856  var end = order ? element2 : element1;
10857
10858  // Get common ancestor container
10859  var range = document.createRange();
10860  range.setStart(start, 0);
10861  range.setEnd(end, 0);
10862  var commonAncestorContainer = range.commonAncestorContainer;
10863
10864  // Both nodes are inside #document
10865
10866  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
10867    if (isOffsetContainer(commonAncestorContainer)) {
10868      return commonAncestorContainer;
10869    }
10870
10871    return getOffsetParent(commonAncestorContainer);
10872  }
10873
10874  // one of the nodes is inside shadowDOM, find which one
10875  var element1root = getRoot(element1);
10876  if (element1root.host) {
10877    return findCommonOffsetParent(element1root.host, element2);
10878  } else {
10879    return findCommonOffsetParent(element1, getRoot(element2).host);
10880  }
10881}
10882
10883/**
10884 * Gets the scroll value of the given element in the given side (top and left)
10885 * @method
10886 * @memberof Popper.Utils
10887 * @argument {Element} element
10888 * @argument {String} side `top` or `left`
10889 * @returns {number} amount of scrolled pixels
10890 */
10891function getScroll(element) {
10892  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
10893
10894  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
10895  var nodeName = element.nodeName;
10896
10897  if (nodeName === 'BODY' || nodeName === 'HTML') {
10898    var html = element.ownerDocument.documentElement;
10899    var scrollingElement = element.ownerDocument.scrollingElement || html;
10900    return scrollingElement[upperSide];
10901  }
10902
10903  return element[upperSide];
10904}
10905
10906/*
10907 * Sum or subtract the element scroll values (left and top) from a given rect object
10908 * @method
10909 * @memberof Popper.Utils
10910 * @param {Object} rect - Rect object you want to change
10911 * @param {HTMLElement} element - The element from the function reads the scroll values
10912 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
10913 * @return {Object} rect - The modifier rect object
10914 */
10915function includeScroll(rect, element) {
10916  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
10917
10918  var scrollTop = getScroll(element, 'top');
10919  var scrollLeft = getScroll(element, 'left');
10920  var modifier = subtract ? -1 : 1;
10921  rect.top += scrollTop * modifier;
10922  rect.bottom += scrollTop * modifier;
10923  rect.left += scrollLeft * modifier;
10924  rect.right += scrollLeft * modifier;
10925  return rect;
10926}
10927
10928/*
10929 * Helper to detect borders of a given element
10930 * @method
10931 * @memberof Popper.Utils
10932 * @param {CSSStyleDeclaration} styles
10933 * Result of `getStyleComputedProperty` on the given element
10934 * @param {String} axis - `x` or `y`
10935 * @return {number} borders - The borders size of the given axis
10936 */
10937
10938function getBordersSize(styles, axis) {
10939  var sideA = axis === 'x' ? 'Left' : 'Top';
10940  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
10941
10942  return parseFloat(styles['border' + sideA + 'Width']
vendor: 2,732 bytes, lines 10942-11041
10942, 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
10943}
10944
10945function getSize(axis, body, html, computedStyle) {
10946  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
10947}
10948
10949function getWindowSizes(document) {
10950  var body = document.body;
10951  var html = document.documentElement;
10952  var computedStyle = isIE(10) && getComputedStyle(html);
10953
10954  return {
10955    height: getSize('Height', body, html, computedStyle),
10956    width: getSize('Width', body, html, computedStyle)
10957  };
10958}
10959
10960var classCallCheck = function (instance, Constructor) {
10961  if (!(instance instanceof Constructor)) {
10962    throw new TypeError("Cannot call a class as a function");
10963  }
10964};
10965
10966var createClass = function () {
10967  function defineProperties(target, props) {
10968    for (var i = 0; i < props.length; i++) {
10969      var descriptor = props[i];
10970      descriptor.enumerable = descriptor.enumerable || false;
10971      descriptor.configurable = true;
10972      if ("value" in descriptor) descriptor.writable = true;
10973      Object.defineProperty(target, descriptor.key, descriptor);
10974    }
10975  }
10976
10977  return function (Constructor, protoProps, staticProps) {
10978    if (protoProps) defineProperties(Constructor.prototype, protoProps);
10979    if (staticProps) defineProperties(Constructor, staticProps);
10980    return Constructor;
10981  };
10982}();
10983
10984
10985
10986
10987
10988var defineProperty = function (obj, key, value) {
10989  if (key in obj) {
10990    Object.defineProperty(obj, key, {
10991      value: value,
10992      enumerable: true,
10993      configurable: true,
10994      writable: true
10995    });
10996  } else {
10997    obj[key] = value;
10998  }
10999
11000  return obj;
11001};
11002
11003var _extends = Object.assign || function (target) {
11004  for (var i = 1; i < arguments.length; i++) {
11005    var source = arguments[i];
11006
11007    for (var key in source) {
11008      if (Object.prototype.hasOwnProperty.call(source, key)) {
11009        target[key] = source[key];
11010      }
11011    }
11012  }
11013
11014  return target;
11015};
11016
11017/**
11018 * Given element offsets, generate an output similar to getBoundingClientRect
11019 * @method
11020 * @memberof Popper.Utils
11021 * @argument {Object} offsets
11022 * @returns {Object} ClientRect like output
11023 */
11024function getClientRect(offsets) {
11025  return _extends({}, offsets, {
11026    right: offsets.left + offsets.width,
11027    bottom: offsets.top + offsets.height
11028  });
11029}
11030
11031/**
11032 * Get bounding client rect of given element
11033 * @method
11034 * @memberof Popper.Utils
11035 * @param {HTMLElement} element
11036 * @return {Object} client rect
11037 */
11038function getBoundingClientRect(element) {
11039  var rect = {};
11040
11041  // IE10 10 FIX: Please, don't ask, the element isn't
vendor: 4,668 bytes, lines 11042-11171
11042  // considered in DOM in some circumstances...
11043  // This isn't reproducible in IE10 compatibility mode of IE11
11044  try {
11045    if (isIE(10)) {
11046      rect = element.getBoundingClientRect();
11047      var scrollTop = getScroll(element, 'top');
11048      var scrollLeft = getScroll(element, 'left');
11049      rect.top += scrollTop;
11050      rect.left += scrollLeft;
11051      rect.bottom += scrollTop;
11052      rect.right += scrollLeft;
11053    } else {
11054      rect = element.getBoundingClientRect();
11055    }
11056  } catch (e) {}
11057
11058  var result = {
11059    left: rect.left,
11060    top: rect.top,
11061    width: rect.right - rect.left,
11062    height: rect.bottom - rect.top
11063  };
11064
11065  // subtract scrollbar size from sizes
11066  var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
11067  var width = sizes.width || element.clientWidth || result.right - result.left;
11068  var height = sizes.height || element.clientHeight || result.bottom - result.top;
11069
11070  var horizScrollbar = element.offsetWidth - width;
11071  var vertScrollbar = element.offsetHeight - height;
11072
11073  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
11074  // we make this check conditional for performance reasons
11075  if (horizScrollbar || vertScrollbar) {
11076    var styles = getStyleComputedProperty(element);
11077    horizScrollbar -= getBordersSize(styles, 'x');
11078    vertScrollbar -= getBordersSize(styles, 'y');
11079
11080    result.width -= horizScrollbar;
11081    result.height -= vertScrollbar;
11082  }
11083
11084  return getClientRect(result);
11085}
11086
11087function getOffsetRectRelativeToArbitraryNode(children, parent) {
11088  var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
11089
11090  var isIE10 = isIE(10);
11091  var isHTML = parent.nodeName === 'HTML';
11092  var childrenRect = getBoundingClientRect(children);
11093  var parentRect = getBoundingClientRect(parent);
11094  var scrollParent = getScrollParent(children);
11095
11096  var styles = getStyleComputedProperty(parent);
11097  var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
11098  var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
11099
11100  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
11101  if (fixedPosition && isHTML) {
11102    parentRect.top = Math.max(parentRect.top, 0);
11103    parentRect.left = Math.max(parentRect.left, 0);
11104  }
11105  var offsets = getClientRect({
11106    top: childrenRect.top - parentRect.top - borderTopWidth,
11107    left: childrenRect.left - parentRect.left - borderLeftWidth,
11108    width: childrenRect.width,
11109    height: childrenRect.height
11110  });
11111  offsets.marginTop = 0;
11112  offsets.marginLeft = 0;
11113
11114  // Subtract margins of documentElement in case it's being used as parent
11115  // we do this only on HTML because it's the only element that behaves
11116  // differently when margins are applied to it. The margins are included in
11117  // the box of the documentElement, in the other cases not.
11118  if (!isIE10 && isHTML) {
11119    var marginTop = parseFloat(styles.marginTop, 10);
11120    var marginLeft = parseFloat(styles.marginLeft, 10);
11121
11122    offsets.top -= borderTopWidth - marginTop;
11123    offsets.bottom -= borderTopWidth - marginTop;
11124    offsets.left -= borderLeftWidth - marginLeft;
11125    offsets.right -= borderLeftWidth - marginLeft;
11126
11127    // Attach marginTop and marginLeft because in some circumstances we may need them
11128    offsets.marginTop = marginTop;
11129    offsets.marginLeft = marginLeft;
11130  }
11131
11132  if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
11133    offsets = includeScroll(offsets, parent);
11134  }
11135
11136  return offsets;
11137}
11138
11139function getViewportOffsetRectRelativeToArtbitraryNode(element) {
11140  var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
11141
11142  var html = element.ownerDocument.documentElement;
11143  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
11144  var width = Math.max(html.clientWidth, window.innerWidth || 0);
11145  var height = Math.max(html.clientHeight, window.innerHeight || 0);
11146
11147  var scrollTop = !excludeScroll ? getScroll(html) : 0;
11148  var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
11149
11150  var offset = {
11151    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
11152    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
11153    width: width,
11154    height: height
11155  };
11156
11157  return getClientRect(offset);
11158}
11159
11160/**
11161 * Check if the given element is fixed or is inside a fixed parent
11162 * @method
11163 * @memberof Popper.Utils
11164 * @argument {Element} element
11165 * @argument {Element} customContainer
11166 * @returns {Boolean} answer to "isFixed?"
11167 */
11168function isFixed(element) {
11169  var nodeName = element.nodeName;
11170  if (nodeName === 'BODY' || nodeName === 'HTML') {
11171    return false;
vendor: 9,912 bytes, lines 11172-11479
11172  }
11173  if (getStyleComputedProperty(element, 'position') === 'fixed') {
11174    return true;
11175  }
11176  var parentNode = getParentNode(element);
11177  if (!parentNode) {
11178    return false;
11179  }
11180  return isFixed(parentNode);
11181}
11182
11183/**
11184 * Finds the first parent of an element that has a transformed property defined
11185 * @method
11186 * @memberof Popper.Utils
11187 * @argument {Element} element
11188 * @returns {Element} first transformed parent or documentElement
11189 */
11190
11191function getFixedPositionOffsetParent(element) {
11192  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
11193  if (!element || !element.parentElement || isIE()) {
11194    return document.documentElement;
11195  }
11196  var el = element.parentElement;
11197  while (el && getStyleComputedProperty(el, 'transform') === 'none') {
11198    el = el.parentElement;
11199  }
11200  return el || document.documentElement;
11201}
11202
11203/**
11204 * Computed the boundaries limits and return them
11205 * @method
11206 * @memberof Popper.Utils
11207 * @param {HTMLElement} popper
11208 * @param {HTMLElement} reference
11209 * @param {number} padding
11210 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
11211 * @param {Boolean} fixedPosition - Is in fixed position mode
11212 * @returns {Object} Coordinates of the boundaries
11213 */
11214function getBoundaries(popper, reference, padding, boundariesElement) {
11215  var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
11216
11217  // NOTE: 1 DOM access here
11218
11219  var boundaries = { top: 0, left: 0 };
11220  var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
11221
11222  // Handle viewport case
11223  if (boundariesElement === 'viewport') {
11224    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
11225  } else {
11226    // Handle other cases based on DOM element used as boundaries
11227    var boundariesNode = void 0;
11228    if (boundariesElement === 'scrollParent') {
11229      boundariesNode = getScrollParent(getParentNode(reference));
11230      if (boundariesNode.nodeName === 'BODY') {
11231        boundariesNode = popper.ownerDocument.documentElement;
11232      }
11233    } else if (boundariesElement === 'window') {
11234      boundariesNode = popper.ownerDocument.documentElement;
11235    } else {
11236      boundariesNode = boundariesElement;
11237    }
11238
11239    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
11240
11241    // In case of HTML, we need a different computation
11242    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
11243      var _getWindowSizes = getWindowSizes(popper.ownerDocument),
11244          height = _getWindowSizes.height,
11245          width = _getWindowSizes.width;
11246
11247      boundaries.top += offsets.top - offsets.marginTop;
11248      boundaries.bottom = height + offsets.top;
11249      boundaries.left += offsets.left - offsets.marginLeft;
11250      boundaries.right = width + offsets.left;
11251    } else {
11252      // for all the other DOM elements, this one is good
11253      boundaries = offsets;
11254    }
11255  }
11256
11257  // Add paddings
11258  padding = padding || 0;
11259  var isPaddingNumber = typeof padding === 'number';
11260  boundaries.left += isPaddingNumber ? padding : padding.left || 0;
11261  boundaries.top += isPaddingNumber ? padding : padding.top || 0;
11262  boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
11263  boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
11264
11265  return boundaries;
11266}
11267
11268function getArea(_ref) {
11269  var width = _ref.width,
11270      height = _ref.height;
11271
11272  return width * height;
11273}
11274
11275/**
11276 * Utility used to transform the `auto` placement to the placement with more
11277 * available space.
11278 * @method
11279 * @memberof Popper.Utils
11280 * @argument {Object} data - The data object generated by update method
11281 * @argument {Object} options - Modifiers configuration and options
11282 * @returns {Object} The data object, properly modified
11283 */
11284function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
11285  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
11286
11287  if (placement.indexOf('auto') === -1) {
11288    return placement;
11289  }
11290
11291  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
11292
11293  var rects = {
11294    top: {
11295      width: boundaries.width,
11296      height: refRect.top - boundaries.top
11297    },
11298    right: {
11299      width: boundaries.right - refRect.right,
11300      height: boundaries.height
11301    },
11302    bottom: {
11303      width: boundaries.width,
11304      height: boundaries.bottom - refRect.bottom
11305    },
11306    left: {
11307      width: refRect.left - boundaries.left,
11308      height: boundaries.height
11309    }
11310  };
11311
11312  var sortedAreas = Object.keys(rects).map(function (key) {
11313    return _extends({
11314      key: key
11315    }, rects[key], {
11316      area: getArea(rects[key])
11317    });
11318  }).sort(function (a, b) {
11319    return b.area - a.area;
11320  });
11321
11322  var filteredAreas = sortedAreas.filter(function (_ref2) {
11323    var width = _ref2.width,
11324        height = _ref2.height;
11325    return width >= popper.clientWidth && height >= popper.clientHeight;
11326  });
11327
11328  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
11329
11330  var variation = placement.split('-')[1];
11331
11332  return computedPlacement + (variation ? '-' + variation : '');
11333}
11334
11335/**
11336 * Get offsets to the reference element
11337 * @method
11338 * @memberof Popper.Utils
11339 * @param {Object} state
11340 * @param {Element} popper - the popper element
11341 * @param {Element} reference - the reference element (the popper will be relative to this)
11342 * @param {Element} fixedPosition - is in fixed position mode
11343 * @returns {Object} An object containing the offsets which will be applied to the popper
11344 */
11345function getReferenceOffsets(state, popper, reference) {
11346  var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
11347
11348  var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
11349  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
11350}
11351
11352/**
11353 * Get the outer sizes of the given element (offset size + margins)
11354 * @method
11355 * @memberof Popper.Utils
11356 * @argument {Element} element
11357 * @returns {Object} object containing width and height properties
11358 */
11359function getOuterSizes(element) {
11360  var window = element.ownerDocument.defaultView;
11361  var styles = window.getComputedStyle(element);
11362  var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
11363  var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
11364  var result = {
11365    width: element.offsetWidth + y,
11366    height: element.offsetHeight + x
11367  };
11368  return result;
11369}
11370
11371/**
11372 * Get the opposite placement of the given one
11373 * @method
11374 * @memberof Popper.Utils
11375 * @argument {String} placement
11376 * @returns {String} flipped placement
11377 */
11378function getOppositePlacement(placement) {
11379  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
11380  return placement.replace(/left|right|bottom|top/g, function (matched) {
11381    return hash[matched];
11382  });
11383}
11384
11385/**
11386 * Get offsets to the popper
11387 * @method
11388 * @memberof Popper.Utils
11389 * @param {Object} position - CSS position the Popper will get applied
11390 * @param {HTMLElement} popper - the popper element
11391 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
11392 * @param {String} placement - one of the valid placement options
11393 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
11394 */
11395function getPopperOffsets(popper, referenceOffsets, placement) {
11396  placement = placement.split('-')[0];
11397
11398  // Get popper node sizes
11399  var popperRect = getOuterSizes(popper);
11400
11401  // Add position, width and height to our offsets object
11402  var popperOffsets = {
11403    width: popperRect.width,
11404    height: popperRect.height
11405  };
11406
11407  // depending by the popper placement we have to compute its offsets slightly differently
11408  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
11409  var mainSide = isHoriz ? 'top' : 'left';
11410  var secondarySide = isHoriz ? 'left' : 'top';
11411  var measurement = isHoriz ? 'height' : 'width';
11412  var secondaryMeasurement = !isHoriz ? 'height' : 'width';
11413
11414  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
11415  if (placement === secondarySide) {
11416    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
11417  } else {
11418    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
11419  }
11420
11421  return popperOffsets;
11422}
11423
11424/**
11425 * Mimics the `find` method of Array
11426 * @method
11427 * @memberof Popper.Utils
11428 * @argument {Array} arr
11429 * @argument prop
11430 * @argument value
11431 * @returns index or -1
11432 */
11433function find(arr, check) {
11434  // use native find if supported
11435  if (Array.prototype.find) {
11436    return arr.find(check);
11437  }
11438
11439  // use `filter` to obtain the same behavior of `find`
11440  return arr.filter(check)[0];
11441}
11442
11443/**
11444 * Return the index of the matching object
11445 * @method
11446 * @memberof Popper.Utils
11447 * @argument {Array} arr
11448 * @argument prop
11449 * @argument value
11450 * @returns index or -1
11451 */
11452function findIndex(arr, prop, value) {
11453  // use native findIndex if supported
11454  if (Array.prototype.findIndex) {
11455    return arr.findIndex(function (cur) {
11456      return cur[prop] === value;
11457    });
11458  }
11459
11460  // use `find` + `indexOf` if `findIndex` isn't supported
11461  var match = find(arr, function (obj) {
11462    return obj[prop] === value;
11463  });
11464  return arr.indexOf(match);
11465}
11466
11467/**
11468 * Loop trough the list of modifiers and run them in order,
11469 * each of them will then edit the data object.
11470 * @method
11471 * @memberof Popper.Utils
11472 * @param {dataObject} data
11473 * @param {Array} modifiers
11474 * @param {String} ends - Optional modifier name used as stopper
11475 * @returns {dataObject}
11476 */
11477function runModifiers(modifiers, data, ends) {
11478  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
11479
vendor: 4,062 bytes, lines 11480-11610
11480  modifiersToRun.forEach(function (modifier) {
11481    if (modifier['function']) {
11482      // eslint-disable-line dot-notation
11483      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
11484    }
11485    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
11486    if (modifier.enabled && isFunction(fn)) {
11487      // Add properties to offsets to make them a complete clientRect object
11488      // we do this before each modifier to make sure the previous one doesn't
11489      // mess with these values
11490      data.offsets.popper = getClientRect(data.offsets.popper);
11491      data.offsets.reference = getClientRect(data.offsets.reference);
11492
11493      data = fn(data, modifier);
11494    }
11495  });
11496
11497  return data;
11498}
11499
11500/**
11501 * Updates the position of the popper, computing the new offsets and applying
11502 * the new style.<br />
11503 * Prefer `scheduleUpdate` over `update` because of performance reasons.
11504 * @method
11505 * @memberof Popper
11506 */
11507function update() {
11508  // if popper is destroyed, don't perform any further update
11509  if (this.state.isDestroyed) {
11510    return;
11511  }
11512
11513  var data = {
11514    instance: this,
11515    styles: {},
11516    arrowStyles: {},
11517    attributes: {},
11518    flipped: false,
11519    offsets: {}
11520  };
11521
11522  // compute reference element offsets
11523  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
11524
11525  // compute auto placement, store placement inside the data object,
11526  // modifiers will be able to edit `placement` if needed
11527  // and refer to originalPlacement to know the original value
11528  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
11529
11530  // store the computed placement inside `originalPlacement`
11531  data.originalPlacement = data.placement;
11532
11533  data.positionFixed = this.options.positionFixed;
11534
11535  // compute the popper offsets
11536  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
11537
11538  data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
11539
11540  // run the modifiers
11541  data = runModifiers(this.modifiers, data);
11542
11543  // the first `update` will call `onCreate` callback
11544  // the other ones will call `onUpdate` callback
11545  if (!this.state.isCreated) {
11546    this.state.isCreated = true;
11547    this.options.onCreate(data);
11548  } else {
11549    this.options.onUpdate(data);
11550  }
11551}
11552
11553/**
11554 * Helper used to know if the given modifier is enabled.
11555 * @method
11556 * @memberof Popper.Utils
11557 * @returns {Boolean}
11558 */
11559function isModifierEnabled(modifiers, modifierName) {
11560  return modifiers.some(function (_ref) {
11561    var name = _ref.name,
11562        enabled = _ref.enabled;
11563    return enabled && name === modifierName;
11564  });
11565}
11566
11567/**
11568 * Get the prefixed supported property name
11569 * @method
11570 * @memberof Popper.Utils
11571 * @argument {String} property (camelCase)
11572 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
11573 */
11574function getSupportedPropertyName(property) {
11575  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
11576  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
11577
11578  for (var i = 0; i < prefixes.length; i++) {
11579    var prefix = prefixes[i];
11580    var toCheck = prefix ? '' + prefix + upperProp : property;
11581    if (typeof document.body.style[toCheck] !== 'undefined') {
11582      return toCheck;
11583    }
11584  }
11585  return null;
11586}
11587
11588/**
11589 * Destroys the popper.
11590 * @method
11591 * @memberof Popper
11592 */
11593function destroy() {
11594  this.state.isDestroyed = true;
11595
11596  // touch DOM only if `applyStyle` modifier is enabled
11597  if (isModifierEnabled(this.modifiers, 'applyStyle')) {
11598    this.popper.removeAttribute('x-placement');
11599    this.popper.style.position = '';
11600    this.popper.style.top = '';
11601    this.popper.style.left = '';
11602    this.popper.style.right = '';
11603    this.popper.style.bottom = '';
11604    this.popper.style.willChange = '';
11605    this.popper.style[getSupportedPropertyName('transform')] = '';
11606  }
11607
11608  this.disableEventListeners();
11609
11610  // remove the popper if user explicit
vendor: 15,762 bytes, lines 11610-12059
11610y asked for the deletion on destroy
11611  // do not use `remove` because IE11 doesn't support it
11612  if (this.options.removeOnDestroy) {
11613    this.popper.parentNode.removeChild(this.popper);
11614  }
11615  return this;
11616}
11617
11618/**
11619 * Get the window associated with the element
11620 * @argument {Element} element
11621 * @returns {Window}
11622 */
11623function getWindow(element) {
11624  var ownerDocument = element.ownerDocument;
11625  return ownerDocument ? ownerDocument.defaultView : window;
11626}
11627
11628function attachToScrollParents(scrollParent, event, callback, scrollParents) {
11629  var isBody = scrollParent.nodeName === 'BODY';
11630  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
11631  target.addEventListener(event, callback, { passive: true });
11632
11633  if (!isBody) {
11634    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
11635  }
11636  scrollParents.push(target);
11637}
11638
11639/**
11640 * Setup needed event listeners used to update the popper position
11641 * @method
11642 * @memberof Popper.Utils
11643 * @private
11644 */
11645function setupEventListeners(reference, options, state, updateBound) {
11646  // Resize event listener on window
11647  state.updateBound = updateBound;
11648  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
11649
11650  // Scroll event listener on scroll parents
11651  var scrollElement = getScrollParent(reference);
11652  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
11653  state.scrollElement = scrollElement;
11654  state.eventsEnabled = true;
11655
11656  return state;
11657}
11658
11659/**
11660 * It will add resize/scroll events and start recalculating
11661 * position of the popper element when they are triggered.
11662 * @method
11663 * @memberof Popper
11664 */
11665function enableEventListeners() {
11666  if (!this.state.eventsEnabled) {
11667    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
11668  }
11669}
11670
11671/**
11672 * Remove event listeners used to update the popper position
11673 * @method
11674 * @memberof Popper.Utils
11675 * @private
11676 */
11677function removeEventListeners(reference, state) {
11678  // Remove resize event listener on window
11679  getWindow(reference).removeEventListener('resize', state.updateBound);
11680
11681  // Remove scroll event listener on scroll parents
11682  state.scrollParents.forEach(function (target) {
11683    target.removeEventListener('scroll', state.updateBound);
11684  });
11685
11686  // Reset state
11687  state.updateBound = null;
11688  state.scrollParents = [];
11689  state.scrollElement = null;
11690  state.eventsEnabled = false;
11691  return state;
11692}
11693
11694/**
11695 * It will remove resize/scroll events and won't recalculate popper position
11696 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
11697 * unless you call `update` method manually.
11698 * @method
11699 * @memberof Popper
11700 */
11701function disableEventListeners() {
11702  if (this.state.eventsEnabled) {
11703    cancelAnimationFrame(this.scheduleUpdate);
11704    this.state = removeEventListeners(this.reference, this.state);
11705  }
11706}
11707
11708/**
11709 * Tells if a given input is a number
11710 * @method
11711 * @memberof Popper.Utils
11712 * @param {*} input to check
11713 * @return {Boolean}
11714 */
11715function isNumeric(n) {
11716  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
11717}
11718
11719/**
11720 * Set the style to the given popper
11721 * @method
11722 * @memberof Popper.Utils
11723 * @argument {Element} element - Element to apply the style to
11724 * @argument {Object} styles
11725 * Object with a list of properties and values which will be applied to the element
11726 */
11727function setStyles(element, styles) {
11728  Object.keys(styles).forEach(function (prop) {
11729    var unit = '';
11730    // add unit if the value is numeric and is one of the following
11731    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
11732      unit = 'px';
11733    }
11734    element.style[prop] = styles[prop] + unit;
11735  });
11736}
11737
11738/**
11739 * Set the attributes to the given popper
11740 * @method
11741 * @memberof Popper.Utils
11742 * @argument {Element} element - Element to apply the attributes to
11743 * @argument {Object} styles
11744 * Object with a list of properties and values which will be applied to the element
11745 */
11746function setAttributes(element, attributes) {
11747  Object.keys(attributes).forEach(function (prop) {
11748    var value = attributes[prop];
11749    if (value !== false) {
11750      element.setAttribute(prop, attributes[prop]);
11751    } else {
11752      element.removeAttribute(prop);
11753    }
11754  });
11755}
11756
11757/**
11758 * @function
11759 * @memberof Modifiers
11760 * @argument {Object} data - The data object generated by `update` method
11761 * @argument {Object} data.styles - List of style properties - values to apply to popper element
11762 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
11763 * @argument {Object} options - Modifiers configuration and options
11764 * @returns {Object} The same data object
11765 */
11766function applyStyle(data) {
11767  // any property present in `data.styles` will be applied to the popper,
11768  // in this way we can make the 3rd party modifiers add custom styles to it
11769  // Be aware, modifiers could override the properties defined in the previous
11770  // lines of this modifier!
11771  setStyles(data.instance.popper, data.styles);
11772
11773  // any property present in `data.attributes` will be applied to the popper,
11774  // they will be set as HTML attributes of the element
11775  setAttributes(data.instance.popper, data.attributes);
11776
11777  // if arrowElement is defined and arrowStyles has some properties
11778  if (data.arrowElement && Object.keys(data.arrowStyles).length) {
11779    setStyles(data.arrowElement, data.arrowStyles);
11780  }
11781
11782  return data;
11783}
11784
11785/**
11786 * Set the x-placement attribute before everything else because it could be used
11787 * to add margins to the popper margins needs to be calculated to get the
11788 * correct popper offsets.
11789 * @method
11790 * @memberof Popper.modifiers
11791 * @param {HTMLElement} reference - The reference element used to position the popper
11792 * @param {HTMLElement} popper - The HTML element used as popper
11793 * @param {Object} options - Popper.js options
11794 */
11795function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
11796  // compute reference element offsets
11797  var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
11798
11799  // compute auto placement, store placement inside the data object,
11800  // modifiers will be able to edit `placement` if needed
11801  // and refer to originalPlacement to know the original value
11802  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
11803
11804  popper.setAttribute('x-placement', placement);
11805
11806  // Apply `position` to popper before anything else because
11807  // without the position applied we can't guarantee correct computations
11808  setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
11809
11810  return options;
11811}
11812
11813/**
11814 * @function
11815 * @memberof Popper.Utils
11816 * @argument {Object} data - The data object generated by `update` method
11817 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
11818 * @returns {Object} The popper's position offsets rounded
11819 *
11820 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
11821 * good as it can be within reason.
11822 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
11823 *
11824 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
11825 * as well on High DPI screens).
11826 *
11827 * Firefox prefers no rounding for positioning and does not have blurriness on
11828 * high DPI screens.
11829 *
11830 * Only horizontal placement and left/right values need to be considered.
11831 */
11832function getRoundedOffsets(data, shouldRound) {
11833  var _data$offsets = data.offsets,
11834      popper = _data$offsets.popper,
11835      reference = _data$offsets.reference;
11836  var round = Math.round,
11837      floor = Math.floor;
11838
11839  var noRound = function noRound(v) {
11840    return v;
11841  };
11842
11843  var referenceWidth = round(reference.width);
11844  var popperWidth = round(popper.width);
11845
11846  var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
11847  var isVariation = data.placement.indexOf('-') !== -1;
11848  var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
11849  var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
11850
11851  var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
11852  var verticalToInteger = !shouldRound ? noRound : round;
11853
11854  return {
11855    left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
11856    top: verticalToInteger(popper.top),
11857    bottom: verticalToInteger(popper.bottom),
11858    right: horizontalToInteger(popper.right)
11859  };
11860}
11861
11862var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
11863
11864/**
11865 * @function
11866 * @memberof Modifiers
11867 * @argument {Object} data - The data object generated by `update` method
11868 * @argument {Object} options - Modifiers configuration and options
11869 * @returns {Object} The data object, properly modified
11870 */
11871function computeStyle(data, options) {
11872  var x = options.x,
11873      y = options.y;
11874  var popper = data.offsets.popper;
11875
11876  // Remove this legacy support in Popper.js v2
11877
11878  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
11879    return modifier.name === 'applyStyle';
11880  }).gpuAcceleration;
11881  if (legacyGpuAccelerationOption !== undefined) {
11882    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
11883  }
11884  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
11885
11886  var offsetParent = getOffsetParent(data.instance.popper);
11887  var offsetParentRect = getBoundingClientRect(offsetParent);
11888
11889  // Styles
11890  var styles = {
11891    position: popper.position
11892  };
11893
11894  var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
11895
11896  var sideA = x === 'bottom' ? 'top' : 'bottom';
11897  var sideB = y === 'right' ? 'left' : 'right';
11898
11899  // if gpuAcceleration is set to `true` and transform is supported,
11900  //  we use `translate3d` to apply the position to the popper we
11901  // automatically use the supported prefixed version if needed
11902  var prefixedProperty = getSupportedPropertyName('transform');
11903
11904  // now, let's make a step back and look at this code closely (wtf?)
11905  // If the content of the popper grows once it's been positioned, it
11906  // may happen that the popper gets misplaced because of the new content
11907  // overflowing its reference element
11908  // To avoid this problem, we provide two options (x and y), which allow
11909  // the consumer to define the offset origin.
11910  // If we position a popper on top of a reference element, we can set
11911  // `x` to `top` to make the popper grow towards its top instead of
11912  // its bottom.
11913  var left = void 0,
11914      top = void 0;
11915  if (sideA === 'bottom') {
11916    // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
11917    // and not the bottom of the html element
11918    if (offsetParent.nodeName === 'HTML') {
11919      top = -offsetParent.clientHeight + offsets.bottom;
11920    } else {
11921      top = -offsetParentRect.height + offsets.bottom;
11922    }
11923  } else {
11924    top = offsets.top;
11925  }
11926  if (sideB === 'right') {
11927    if (offsetParent.nodeName === 'HTML') {
11928      left = -offsetParent.clientWidth + offsets.right;
11929    } else {
11930      left = -offsetParentRect.width + offsets.right;
11931    }
11932  } else {
11933    left = offsets.left;
11934  }
11935  if (gpuAcceleration && prefixedProperty) {
11936    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
11937    styles[sideA] = 0;
11938    styles[sideB] = 0;
11939    styles.willChange = 'transform';
11940  } else {
11941    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
11942    var invertTop = sideA === 'bottom' ? -1 : 1;
11943    var invertLeft = sideB === 'right' ? -1 : 1;
11944    styles[sideA] = top * invertTop;
11945    styles[sideB] = left * invertLeft;
11946    styles.willChange = sideA + ', ' + sideB;
11947  }
11948
11949  // Attributes
11950  var attributes = {
11951    'x-placement': data.placement
11952  };
11953
11954  // Update `data` attributes, styles and arrowStyles
11955  data.attributes = _extends({}, attributes, data.attributes);
11956  data.styles = _extends({}, styles, data.styles);
11957  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
11958
11959  return data;
11960}
11961
11962/**
11963 * Helper used to know if the given modifier depends from another one.<br />
11964 * It checks if the needed modifier is listed and enabled.
11965 * @method
11966 * @memberof Popper.Utils
11967 * @param {Array} modifiers - list of modifiers
11968 * @param {String} requestingName - name of requesting modifier
11969 * @param {String} requestedName - name of requested modifier
11970 * @returns {Boolean}
11971 */
11972function isModifierRequired(modifiers, requestingName, requestedName) {
11973  var requesting = find(modifiers, function (_ref) {
11974    var name = _ref.name;
11975    return name === requestingName;
11976  });
11977
11978  var isRequired = !!requesting && modifiers.some(function (modifier) {
11979    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
11980  });
11981
11982  if (!isRequired) {
11983    var _requesting = '`' + requestingName + '`';
11984    var requested = '`' + requestedName + '`';
11985    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
11986  }
11987  return isRequired;
11988}
11989
11990/**
11991 * @function
11992 * @memberof Modifiers
11993 * @argument {Object} data - The data object generated by update method
11994 * @argument {Object} options - Modifiers configuration and options
11995 * @returns {Object} The data object, properly modified
11996 */
11997function arrow(data, options) {
11998  var _data$offsets$arrow;
11999
12000  // arrow depends on keepTogether in order to work
12001  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
12002    return data;
12003  }
12004
12005  var arrowElement = options.element;
12006
12007  // if arrowElement is a string, suppose it's a CSS selector
12008  if (typeof arrowElement === 'string') {
12009    arrowElement = data.instance.popper.querySelector(arrowElement);
12010
12011    // if arrowElement is not found, don't run the modifier
12012    if (!arrowElement) {
12013      return data;
12014    }
12015  } else {
12016    // if the arrowElement isn't a query selector we must check that the
12017    // provided DOM node is child of its popper node
12018    if (!data.instance.popper.contains(arrowElement)) {
12019      console.warn('WARNING: `arrow.element` must be child of its popper element!');
12020      return data;
12021    }
12022  }
12023
12024  var placement = data.placement.split('-')[0];
12025  var _data$offsets = data.offsets,
12026      popper = _data$offsets.popper,
12027      reference = _data$offsets.reference;
12028
12029  var isVertical = ['left', 'right'].indexOf(placement) !== -1;
12030
12031  var len = isVertical ? 'height' : 'width';
12032  var sideCapitalized = isVertical ? 'Top' : 'Left';
12033  var side = sideCapitalized.toLowerCase();
12034  var altSide = isVertical ? 'left' : 'top';
12035  var opSide = isVertical ? 'bottom' : 'right';
12036  var arrowElementSize = getOuterSizes(arrowElement)[len];
12037
12038  //
12039  // extends keepTogether behavior making sure the popper and its
12040  // reference have enough pixels in conjunction
12041  //
12042
12043  // top/left side
12044  if (reference[opSide] - arrowElementSize < popper[side]) {
12045    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
12046  }
12047  // bottom/right side
12048  if (reference[side] + arrowElementSize > popper[opSide]) {
12049    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
12050  }
12051  data.offsets.popper = getClientRect(data.offsets.popper);
12052
12053  // compute center of the popper
12054  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
12055
12056  // Compute the sideValue using the updated popper offsets
12057  // take popper margin in account because we don't have this info available
12058  var css = getStyleComputedProperty(data.instance.popper);
12059  var popperMarginSide = parseFloat(css['margin' + sideCapitalized]
12059, 10);
12060  var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10
vendor: 21,597 bytes, lines 12060-12670
12060);
12061  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
12062
12063  // prevent arrowElement from being placed not contiguously to its popper
12064  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
12065
12066  data.arrowElement = arrowElement;
12067  data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
12068
12069  return data;
12070}
12071
12072/**
12073 * Get the opposite placement variation of the given one
12074 * @method
12075 * @memberof Popper.Utils
12076 * @argument {String} placement variation
12077 * @returns {String} flipped placement variation
12078 */
12079function getOppositeVariation(variation) {
12080  if (variation === 'end') {
12081    return 'start';
12082  } else if (variation === 'start') {
12083    return 'end';
12084  }
12085  return variation;
12086}
12087
12088/**
12089 * List of accepted placements to use as values of the `placement` option.<br />
12090 * Valid placements are:
12091 * - `auto`
12092 * - `top`
12093 * - `right`
12094 * - `bottom`
12095 * - `left`
12096 *
12097 * Each placement can have a variation from this list:
12098 * - `-start`
12099 * - `-end`
12100 *
12101 * Variations are interpreted easily if you think of them as the left to right
12102 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
12103 * is right.<br />
12104 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
12105 *
12106 * Some valid examples are:
12107 * - `top-end` (on top of reference, right aligned)
12108 * - `right-start` (on right of reference, top aligned)
12109 * - `bottom` (on bottom, centered)
12110 * - `auto-end` (on the side with more space available, alignment depends by placement)
12111 *
12112 * @static
12113 * @type {Array}
12114 * @enum {String}
12115 * @readonly
12116 * @method placements
12117 * @memberof Popper
12118 */
12119var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
12120
12121// Get rid of `auto` `auto-start` and `auto-end`
12122var validPlacements = placements.slice(3);
12123
12124/**
12125 * Given an initial placement, returns all the subsequent placements
12126 * clockwise (or counter-clockwise).
12127 *
12128 * @method
12129 * @memberof Popper.Utils
12130 * @argument {String} placement - A valid placement (it accepts variations)
12131 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
12132 * @returns {Array} placements including their variations
12133 */
12134function clockwise(placement) {
12135  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
12136
12137  var index = validPlacements.indexOf(placement);
12138  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
12139  return counter ? arr.reverse() : arr;
12140}
12141
12142var BEHAVIORS = {
12143  FLIP: 'flip',
12144  CLOCKWISE: 'clockwise',
12145  COUNTERCLOCKWISE: 'counterclockwise'
12146};
12147
12148/**
12149 * @function
12150 * @memberof Modifiers
12151 * @argument {Object} data - The data object generated by update method
12152 * @argument {Object} options - Modifiers configuration and options
12153 * @returns {Object} The data object, properly modified
12154 */
12155function flip(data, options) {
12156  // if `inner` modifier is enabled, we can't use the `flip` modifier
12157  if (isModifierEnabled(data.instance.modifiers, 'inner')) {
12158    return data;
12159  }
12160
12161  if (data.flipped && data.placement === data.originalPlacement) {
12162    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
12163    return data;
12164  }
12165
12166  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
12167
12168  var placement = data.placement.split('-')[0];
12169  var placementOpposite = getOppositePlacement(placement);
12170  var variation = data.placement.split('-')[1] || '';
12171
12172  var flipOrder = [];
12173
12174  switch (options.behavior) {
12175    case BEHAVIORS.FLIP:
12176      flipOrder = [placement, placementOpposite];
12177      break;
12178    case BEHAVIORS.CLOCKWISE:
12179      flipOrder = clockwise(placement);
12180      break;
12181    case BEHAVIORS.COUNTERCLOCKWISE:
12182      flipOrder = clockwise(placement, true);
12183      break;
12184    default:
12185      flipOrder = options.behavior;
12186  }
12187
12188  flipOrder.forEach(function (step, index) {
12189    if (placement !== step || flipOrder.length === index + 1) {
12190      return data;
12191    }
12192
12193    placement = data.placement.split('-')[0];
12194    placementOpposite = getOppositePlacement(placement);
12195
12196    var popperOffsets = data.offsets.popper;
12197    var refOffsets = data.offsets.reference;
12198
12199    // using floor because the reference offsets may contain decimals we are not going to consider here
12200    var floor = Math.floor;
12201    var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
12202
12203    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
12204    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
12205    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
12206    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
12207
12208    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
12209
12210    // flip the variation if required
12211    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
12212
12213    // flips variation if reference element overflows boundaries
12214    var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
12215
12216    // flips variation if popper content overflows boundaries
12217    var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
12218
12219    var flippedVariation = flippedVariationByRef || flippedVariationByContent;
12220
12221    if (overlapsRef || overflowsBoundaries || flippedVariation) {
12222      // this boolean to detect any flip loop
12223      data.flipped = true;
12224
12225      if (overlapsRef || overflowsBoundaries) {
12226        placement = flipOrder[index + 1];
12227      }
12228
12229      if (flippedVariation) {
12230        variation = getOppositeVariation(variation);
12231      }
12232
12233      data.placement = placement + (variation ? '-' + variation : '');
12234
12235      // this object contains `position`, we want to preserve it along with
12236      // any additional property we may add in the future
12237      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
12238
12239      data = runModifiers(data.instance.modifiers, data, 'flip');
12240    }
12241  });
12242  return data;
12243}
12244
12245/**
12246 * @function
12247 * @memberof Modifiers
12248 * @argument {Object} data - The data object generated by update method
12249 * @argument {Object} options - Modifiers configuration and options
12250 * @returns {Object} The data object, properly modified
12251 */
12252function keepTogether(data) {
12253  var _data$offsets = data.offsets,
12254      popper = _data$offsets.popper,
12255      reference = _data$offsets.reference;
12256
12257  var placement = data.placement.split('-')[0];
12258  var floor = Math.floor;
12259  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
12260  var side = isVertical ? 'right' : 'bottom';
12261  var opSide = isVertical ? 'left' : 'top';
12262  var measurement = isVertical ? 'width' : 'height';
12263
12264  if (popper[side] < floor(reference[opSide])) {
12265    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
12266  }
12267  if (popper[opSide] > floor(reference[side])) {
12268    data.offsets.popper[opSide] = floor(reference[side]);
12269  }
12270
12271  return data;
12272}
12273
12274/**
12275 * Converts a string containing value + unit into a px value number
12276 * @function
12277 * @memberof {modifiers~offset}
12278 * @private
12279 * @argument {String} str - Value + unit string
12280 * @argument {String} measurement - `height` or `width`
12281 * @argument {Object} popperOffsets
12282 * @argument {Object} referenceOffsets
12283 * @returns {Number|String}
12284 * Value in pixels, or original string if no values were extracted
12285 */
12286function toValue(str, measurement, popperOffsets, referenceOffsets) {
12287  // separate value from unit
12288  var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
12289  var value = +split[1];
12290  var unit = split[2];
12291
12292  // If it's not a number it's an operator, I guess
12293  if (!value) {
12294    return str;
12295  }
12296
12297  if (unit.indexOf('%') === 0) {
12298    var element = void 0;
12299    switch (unit) {
12300      case '%p':
12301        element = popperOffsets;
12302        break;
12303      case '%':
12304      case '%r':
12305      default:
12306        element = referenceOffsets;
12307    }
12308
12309    var rect = getClientRect(element);
12310    return rect[measurement] / 100 * value;
12311  } else if (unit === 'vh' || unit === 'vw') {
12312    // if is a vh or vw, we calculate the size based on the viewport
12313    var size = void 0;
12314    if (unit === 'vh') {
12315      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
12316    } else {
12317      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
12318    }
12319    return size / 100 * value;
12320  } else {
12321    // if is an explicit pixel unit, we get rid of the unit and keep the value
12322    // if is an implicit unit, it's px, and we return just the value
12323    return value;
12324  }
12325}
12326
12327/**
12328 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
12329 * @function
12330 * @memberof {modifiers~offset}
12331 * @private
12332 * @argument {String} offset
12333 * @argument {Object} popperOffsets
12334 * @argument {Object} referenceOffsets
12335 * @argument {String} basePlacement
12336 * @returns {Array} a two cells array with x and y offsets in numbers
12337 */
12338function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
12339  var offsets = [0, 0];
12340
12341  // Use height if placement is left or right and index is 0 otherwise use width
12342  // in this way the first offset will use an axis and the second one
12343  // will use the other one
12344  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
12345
12346  // Split the offset string to obtain a list of values and operands
12347  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
12348  var fragments = offset.split(/(\+|\-)/).map(function (frag) {
12349    return frag.trim();
12350  });
12351
12352  // Detect if the offset string contains a pair of values or a single one
12353  // they could be separated by comma or space
12354  var divider = fragments.indexOf(find(fragments, function (frag) {
12355    return frag.search(/,|\s/) !== -1;
12356  }));
12357
12358  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
12359    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
12360  }
12361
12362  // If divider is found, we divide the list of values and operands to divide
12363  // them by ofset X and Y.
12364  var splitRegex = /\s*,\s*|\s+/;
12365  var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
12366
12367  // Convert the values with units to absolute pixels to allow our computations
12368  ops = ops.map(function (op, index) {
12369    // Most of the units rely on the orientation of the popper
12370    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
12371    var mergeWithPrevious = false;
12372    return op
12373    // This aggregates any `+` or `-` sign that aren't considered operators
12374    // e.g.: 10 + +5 => [10, +, +5]
12375    .reduce(function (a, b) {
12376      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
12377        a[a.length - 1] = b;
12378        mergeWithPrevious = true;
12379        return a;
12380      } else if (mergeWithPrevious) {
12381        a[a.length - 1] += b;
12382        mergeWithPrevious = false;
12383        return a;
12384      } else {
12385        return a.concat(b);
12386      }
12387    }, [])
12388    // Here we convert the string values into number values (in px)
12389    .map(function (str) {
12390      return toValue(str, measurement, popperOffsets, referenceOffsets);
12391    });
12392  });
12393
12394  // Loop trough the offsets arrays and execute the operations
12395  ops.forEach(function (op, index) {
12396    op.forEach(function (frag, index2) {
12397      if (isNumeric(frag)) {
12398        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
12399      }
12400    });
12401  });
12402  return offsets;
12403}
12404
12405/**
12406 * @function
12407 * @memberof Modifiers
12408 * @argument {Object} data - The data object generated by update method
12409 * @argument {Object} options - Modifiers configuration and options
12410 * @argument {Number|String} options.offset=0
12411 * The offset value as described in the modifier description
12412 * @returns {Object} The data object, properly modified
12413 */
12414function offset(data, _ref) {
12415  var offset = _ref.offset;
12416  var placement = data.placement,
12417      _data$offsets = data.offsets,
12418      popper = _data$offsets.popper,
12419      reference = _data$offsets.reference;
12420
12421  var basePlacement = placement.split('-')[0];
12422
12423  var offsets = void 0;
12424  if (isNumeric(+offset)) {
12425    offsets = [+offset, 0];
12426  } else {
12427    offsets = parseOffset(offset, popper, reference, basePlacement);
12428  }
12429
12430  if (basePlacement === 'left') {
12431    popper.top += offsets[0];
12432    popper.left -= offsets[1];
12433  } else if (basePlacement === 'right') {
12434    popper.top += offsets[0];
12435    popper.left += offsets[1];
12436  } else if (basePlacement === 'top') {
12437    popper.left += offsets[0];
12438    popper.top -= offsets[1];
12439  } else if (basePlacement === 'bottom') {
12440    popper.left += offsets[0];
12441    popper.top += offsets[1];
12442  }
12443
12444  data.popper = popper;
12445  return data;
12446}
12447
12448/**
12449 * @function
12450 * @memberof Modifiers
12451 * @argument {Object} data - The data object generated by `update` method
12452 * @argument {Object} options - Modifiers configuration and options
12453 * @returns {Object} The data object, properly modified
12454 */
12455function preventOverflow(data, options) {
12456  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
12457
12458  // If offsetParent is the reference element, we really want to
12459  // go one step up and use the next offsetParent as reference to
12460  // avoid to make this modifier completely useless and look like broken
12461  if (data.instance.reference === boundariesElement) {
12462    boundariesElement = getOffsetParent(boundariesElement);
12463  }
12464
12465  // NOTE: DOM access here
12466  // resets the popper's position so that the document size can be calculated excluding
12467  // the size of the popper element itself
12468  var transformProp = getSupportedPropertyName('transform');
12469  var popperStyles = data.instance.popper.style; // assignment to help minification
12470  var top = popperStyles.top,
12471      left = popperStyles.left,
12472      transform = popperStyles[transformProp];
12473
12474  popperStyles.top = '';
12475  popperStyles.left = '';
12476  popperStyles[transformProp] = '';
12477
12478  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
12479
12480  // NOTE: DOM access here
12481  // restores the original style properties after the offsets have been computed
12482  popperStyles.top = top;
12483  popperStyles.left = left;
12484  popperStyles[transformProp] = transform;
12485
12486  options.boundaries = boundaries;
12487
12488  var order = options.priority;
12489  var popper = data.offsets.popper;
12490
12491  var check = {
12492    primary: function primary(placement) {
12493      var value = popper[placement];
12494      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
12495        value = Math.max(popper[placement], boundaries[placement]);
12496      }
12497      return defineProperty({}, placement, value);
12498    },
12499    secondary: function secondary(placement) {
12500      var mainSide = placement === 'right' ? 'left' : 'top';
12501      var value = popper[mainSide];
12502      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
12503        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
12504      }
12505      return defineProperty({}, mainSide, value);
12506    }
12507  };
12508
12509  order.forEach(function (placement) {
12510    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
12511    popper = _extends({}, popper, check[side](placement));
12512  });
12513
12514  data.offsets.popper = popper;
12515
12516  return data;
12517}
12518
12519/**
12520 * @function
12521 * @memberof Modifiers
12522 * @argument {Object} data - The data object generated by `update` method
12523 * @argument {Object} options - Modifiers configuration and options
12524 * @returns {Object} The data object, properly modified
12525 */
12526function shift(data) {
12527  var placement = data.placement;
12528  var basePlacement = placement.split('-')[0];
12529  var shiftvariation = placement.split('-')[1];
12530
12531  // if shift shiftvariation is specified, run the modifier
12532  if (shiftvariation) {
12533    var _data$offsets = data.offsets,
12534        reference = _data$offsets.reference,
12535        popper = _data$offsets.popper;
12536
12537    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
12538    var side = isVertical ? 'left' : 'top';
12539    var measurement = isVertical ? 'width' : 'height';
12540
12541    var shiftOffsets = {
12542      start: defineProperty({}, side, reference[side]),
12543      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
12544    };
12545
12546    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
12547  }
12548
12549  return data;
12550}
12551
12552/**
12553 * @function
12554 * @memberof Modifiers
12555 * @argument {Object} data - The data object generated by update method
12556 * @argument {Object} options - Modifiers configuration and options
12557 * @returns {Object} The data object, properly modified
12558 */
12559function hide(data) {
12560  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
12561    return data;
12562  }
12563
12564  var refRect = data.offsets.reference;
12565  var bound = find(data.instance.modifiers, function (modifier) {
12566    return modifier.name === 'preventOverflow';
12567  }).boundaries;
12568
12569  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
12570    // Avoid unnecessary DOM access if visibility hasn't changed
12571    if (data.hide === true) {
12572      return data;
12573    }
12574
12575    data.hide = true;
12576    data.attributes['x-out-of-boundaries'] = '';
12577  } else {
12578    // Avoid unnecessary DOM access if visibility hasn't changed
12579    if (data.hide === false) {
12580      return data;
12581    }
12582
12583    data.hide = false;
12584    data.attributes['x-out-of-boundaries'] = false;
12585  }
12586
12587  return data;
12588}
12589
12590/**
12591 * @function
12592 * @memberof Modifiers
12593 * @argument {Object} data - The data object generated by `update` method
12594 * @argument {Object} options - Modifiers configuration and options
12595 * @returns {Object} The data object, properly modified
12596 */
12597function inner(data) {
12598  var placement = data.placement;
12599  var basePlacement = placement.split('-')[0];
12600  var _data$offsets = data.offsets,
12601      popper = _data$offsets.popper,
12602      reference = _data$offsets.reference;
12603
12604  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
12605
12606  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
12607
12608  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
12609
12610  data.placement = getOppositePlacement(placement);
12611  data.offsets.popper = getClientRect(popper);
12612
12613  return data;
12614}
12615
12616/**
12617 * Modifier function, each modifier can have a function of this type assigned
12618 * to its `fn` property.<br />
12619 * These functions will be called on each update, this means that you must
12620 * make sure they are performant enough to avoid performance bottlenecks.
12621 *
12622 * @function ModifierFn
12623 * @argument {dataObject} data - The data object generated by `update` method
12624 * @argument {Object} options - Modifiers configuration and options
12625 * @returns {dataObject} The data object, properly modified
12626 */
12627
12628/**
12629 * Modifiers are plugins used to alter the behavior of your poppers.<br />
12630 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
12631 * needed by the library.
12632 *
12633 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
12634 * All the other properties are configurations that could be tweaked.
12635 * @namespace modifiers
12636 */
12637var modifiers = {
12638  /**
12639   * Modifier used to shift the popper on the start or end of its reference
12640   * element.<br />
12641   * It will read the variation of the `placement` property.<br />
12642   * It can be one either `-end` or `-start`.
12643   * @memberof modifiers
12644   * @inner
12645   */
12646  shift: {
12647    /** @prop {number} order=100 - Index used to define the order of execution */
12648    order: 100,
12649    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12650    enabled: true,
12651    /** @prop {ModifierFn} */
12652    fn: shift
12653  },
12654
12655  /**
12656   * The `offset` modifier can shift your popper on both its axis.
12657   *
12658   * It accepts the following units:
12659   * - `px` or unit-less, interpreted as pixels
12660   * - `%` or `%r`, percentage relative to the length of the reference element
12661   * - `%p`, percentage relative to the length of the popper element
12662   * - `vw`, CSS viewport width unit
12663   * - `vh`, CSS viewport height unit
12664   *
12665   * For length is intended the main axis relative to the placement of the popper.<br />
12666   * This means that if the placement is `top` or `bottom`, the length will be the
12667   * `width`. In case of `left` or `right`, it will be the `height`.
12668   *
12669   * You can provide a single value (as `Number` or `String`), or a pair of values
12670   * as `String` divided by a comma or one (or more) white space
vendor: 9,957 bytes, lines 12670-12942
12670s.<br />
12671   * The latter is a deprecated method because it leads to confusion and will be
12672   * removed in v2.<br />
12673   * Additionally, it accepts additions and subtractions between different units.
12674   * Note that multiplications and divisions aren't supported.
12675   *
12676   * Valid examples are:
12677   * ```
12678   * 10
12679   * '10%'
12680   * '10, 10'
12681   * '10%, 10'
12682   * '10 + 10%'
12683   * '10 - 5vh + 3%'
12684   * '-10px + 5vh, 5px - 6%'
12685   * ```
12686   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
12687   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
12688   * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
12689   *
12690   * @memberof modifiers
12691   * @inner
12692   */
12693  offset: {
12694    /** @prop {number} order=200 - Index used to define the order of execution */
12695    order: 200,
12696    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12697    enabled: true,
12698    /** @prop {ModifierFn} */
12699    fn: offset,
12700    /** @prop {Number|String} offset=0
12701     * The offset value as described in the modifier description
12702     */
12703    offset: 0
12704  },
12705
12706  /**
12707   * Modifier used to prevent the popper from being positioned outside the boundary.
12708   *
12709   * A scenario exists where the reference itself is not within the boundaries.<br />
12710   * We can say it has "escaped the boundaries" — or just "escaped".<br />
12711   * In this case we need to decide whether the popper should either:
12712   *
12713   * - detach from the reference and remain "trapped" in the boundaries, or
12714   * - if it should ignore the boundary and "escape with its reference"
12715   *
12716   * When `escapeWithReference` is set to`true` and reference is completely
12717   * outside its boundaries, the popper will overflow (or completely leave)
12718   * the boundaries in order to remain attached to the edge of the reference.
12719   *
12720   * @memberof modifiers
12721   * @inner
12722   */
12723  preventOverflow: {
12724    /** @prop {number} order=300 - Index used to define the order of execution */
12725    order: 300,
12726    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12727    enabled: true,
12728    /** @prop {ModifierFn} */
12729    fn: preventOverflow,
12730    /**
12731     * @prop {Array} [priority=['left','right','top','bottom']]
12732     * Popper will try to prevent overflow following these priorities by default,
12733     * then, it could overflow on the left and on top of the `boundariesElement`
12734     */
12735    priority: ['left', 'right', 'top', 'bottom'],
12736    /**
12737     * @prop {number} padding=5
12738     * Amount of pixel used to define a minimum distance between the boundaries
12739     * and the popper. This makes sure the popper always has a little padding
12740     * between the edges of its container
12741     */
12742    padding: 5,
12743    /**
12744     * @prop {String|HTMLElement} boundariesElement='scrollParent'
12745     * Boundaries used by the modifier. Can be `scrollParent`, `window`,
12746     * `viewport` or any DOM element.
12747     */
12748    boundariesElement: 'scrollParent'
12749  },
12750
12751  /**
12752   * Modifier used to make sure the reference and its popper stay near each other
12753   * without leaving any gap between the two. Especially useful when the arrow is
12754   * enabled and you want to ensure that it points to its reference element.
12755   * It cares only about the first axis. You can still have poppers with margin
12756   * between the popper and its reference element.
12757   * @memberof modifiers
12758   * @inner
12759   */
12760  keepTogether: {
12761    /** @prop {number} order=400 - Index used to define the order of execution */
12762    order: 400,
12763    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12764    enabled: true,
12765    /** @prop {ModifierFn} */
12766    fn: keepTogether
12767  },
12768
12769  /**
12770   * This modifier is used to move the `arrowElement` of the popper to make
12771   * sure it is positioned between the reference element and its popper element.
12772   * It will read the outer size of the `arrowElement` node to detect how many
12773   * pixels of conjunction are needed.
12774   *
12775   * It has no effect if no `arrowElement` is provided.
12776   * @memberof modifiers
12777   * @inner
12778   */
12779  arrow: {
12780    /** @prop {number} order=500 - Index used to define the order of execution */
12781    order: 500,
12782    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12783    enabled: true,
12784    /** @prop {ModifierFn} */
12785    fn: arrow,
12786    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
12787    element: '[x-arrow]'
12788  },
12789
12790  /**
12791   * Modifier used to flip the popper's placement when it starts to overlap its
12792   * reference element.
12793   *
12794   * Requires the `preventOverflow` modifier before it in order to work.
12795   *
12796   * **NOTE:** this modifier will interrupt the current update cycle and will
12797   * restart it if it detects the need to flip the placement.
12798   * @memberof modifiers
12799   * @inner
12800   */
12801  flip: {
12802    /** @prop {number} order=600 - Index used to define the order of execution */
12803    order: 600,
12804    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12805    enabled: true,
12806    /** @prop {ModifierFn} */
12807    fn: flip,
12808    /**
12809     * @prop {String|Array} behavior='flip'
12810     * The behavior used to change the popper's placement. It can be one of
12811     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
12812     * placements (with optional variations)
12813     */
12814    behavior: 'flip',
12815    /**
12816     * @prop {number} padding=5
12817     * The popper will flip if it hits the edges of the `boundariesElement`
12818     */
12819    padding: 5,
12820    /**
12821     * @prop {String|HTMLElement} boundariesElement='viewport'
12822     * The element which will define the boundaries of the popper position.
12823     * The popper will never be placed outside of the defined boundaries
12824     * (except if `keepTogether` is enabled)
12825     */
12826    boundariesElement: 'viewport',
12827    /**
12828     * @prop {Boolean} flipVariations=false
12829     * The popper will switch placement variation between `-start` and `-end` when
12830     * the reference element overlaps its boundaries.
12831     *
12832     * The original placement should have a set variation.
12833     */
12834    flipVariations: false,
12835    /**
12836     * @prop {Boolean} flipVariationsByContent=false
12837     * The popper will switch placement variation between `-start` and `-end` when
12838     * the popper element overlaps its reference boundaries.
12839     *
12840     * The original placement should have a set variation.
12841     */
12842    flipVariationsByContent: false
12843  },
12844
12845  /**
12846   * Modifier used to make the popper flow toward the inner of the reference element.
12847   * By default, when this modifier is disabled, the popper will be placed outside
12848   * the reference element.
12849   * @memberof modifiers
12850   * @inner
12851   */
12852  inner: {
12853    /** @prop {number} order=700 - Index used to define the order of execution */
12854    order: 700,
12855    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
12856    enabled: false,
12857    /** @prop {ModifierFn} */
12858    fn: inner
12859  },
12860
12861  /**
12862   * Modifier used to hide the popper when its reference element is outside of the
12863   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
12864   * be used to hide with a CSS selector the popper when its reference is
12865   * out of boundaries.
12866   *
12867   * Requires the `preventOverflow` modifier before it in order to work.
12868   * @memberof modifiers
12869   * @inner
12870   */
12871  hide: {
12872    /** @prop {number} order=800 - Index used to define the order of execution */
12873    order: 800,
12874    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12875    enabled: true,
12876    /** @prop {ModifierFn} */
12877    fn: hide
12878  },
12879
12880  /**
12881   * Computes the style that will be applied to the popper element to gets
12882   * properly positioned.
12883   *
12884   * Note that this modifier will not touch the DOM, it just prepares the styles
12885   * so that `applyStyle` modifier can apply it. This separation is useful
12886   * in case you need to replace `applyStyle` with a custom implementation.
12887   *
12888   * This modifier has `850` as `order` value to maintain backward compatibility
12889   * with previous versions of Popper.js. Expect the modifiers ordering method
12890   * to change in future major versions of the library.
12891   *
12892   * @memberof modifiers
12893   * @inner
12894   */
12895  computeStyle: {
12896    /** @prop {number} order=850 - Index used to define the order of execution */
12897    order: 850,
12898    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12899    enabled: true,
12900    /** @prop {ModifierFn} */
12901    fn: computeStyle,
12902    /**
12903     * @prop {Boolean} gpuAcceleration=true
12904     * If true, it uses the CSS 3D transformation to position the popper.
12905     * Otherwise, it will use the `top` and `left` properties
12906     */
12907    gpuAcceleration: true,
12908    /**
12909     * @prop {string} [x='bottom']
12910     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
12911     * Change this if your popper should grow in a direction different from `bottom`
12912     */
12913    x: 'bottom',
12914    /**
12915     * @prop {string} [x='left']
12916     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
12917     * Change this if your popper should grow in a direction different from `right`
12918     */
12919    y: 'right'
12920  },
12921
12922  /**
12923   * Applies the computed styles to the popper element.
12924   *
12925   * All the DOM manipulations are limited to this modifier. This is useful in case
12926   * you want to integrate Popper.js inside a framework or view library and you
12927   * want to delegate all the DOM manipulations to it.
12928   *
12929   * Note that if you disable this modifier, you must make sure the popper element
12930   * has its position set to `absolute` before Popper.js can do its work!
12931   *
12932   * Just disable this modifier and define your own to achieve the desired effect.
12933   *
12934   * @memberof modifiers
12935   * @inner
12936   */
12937  applyStyle: {
12938    /** @prop {number} order=900 - Index used to define the order of execution */
12939    order: 900,
12940    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12941    enabled: true,
12942    /** @prop {ModifierFn} */
vendor: 9,127 bytes, lines 12943-13207
12943    fn: applyStyle,
12944    /** @prop {Function} */
12945    onLoad: applyStyleOnLoad,
12946    /**
12947     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
12948     * @prop {Boolean} gpuAcceleration=true
12949     * If true, it uses the CSS 3D transformation to position the popper.
12950     * Otherwise, it will use the `top` and `left` properties
12951     */
12952    gpuAcceleration: undefined
12953  }
12954};
12955
12956/**
12957 * The `dataObject` is an object containing all the information used by Popper.js.
12958 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
12959 * @name dataObject
12960 * @property {Object} data.instance The Popper.js instance
12961 * @property {String} data.placement Placement applied to popper
12962 * @property {String} data.originalPlacement Placement originally defined on init
12963 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
12964 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
12965 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
12966 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
12967 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
12968 * @property {Object} data.boundaries Offsets of the popper boundaries
12969 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
12970 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
12971 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
12972 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
12973 */
12974
12975/**
12976 * Default options provided to Popper.js constructor.<br />
12977 * These can be overridden using the `options` argument of Popper.js.<br />
12978 * To override an option, simply pass an object with the same
12979 * structure of the `options` object, as the 3rd argument. For example:
12980 * ```
12981 * new Popper(ref, pop, {
12982 *   modifiers: {
12983 *     preventOverflow: { enabled: false }
12984 *   }
12985 * })
12986 * ```
12987 * @type {Object}
12988 * @static
12989 * @memberof Popper
12990 */
12991var Defaults = {
12992  /**
12993   * Popper's placement.
12994   * @prop {Popper.placements} placement='bottom'
12995   */
12996  placement: 'bottom',
12997
12998  /**
12999   * Set this to true if you want popper to position it self in 'fixed' mode
13000   * @prop {Boolean} positionFixed=false
13001   */
13002  positionFixed: false,
13003
13004  /**
13005   * Whether events (resize, scroll) are initially enabled.
13006   * @prop {Boolean} eventsEnabled=true
13007   */
13008  eventsEnabled: true,
13009
13010  /**
13011   * Set to true if you want to automatically remove the popper when
13012   * you call the `destroy` method.
13013   * @prop {Boolean} removeOnDestroy=false
13014   */
13015  removeOnDestroy: false,
13016
13017  /**
13018   * Callback called when the popper is created.<br />
13019   * By default, it is set to no-op.<br />
13020   * Access Popper.js instance with `data.instance`.
13021   * @prop {onCreate}
13022   */
13023  onCreate: function onCreate() {},
13024
13025  /**
13026   * Callback called when the popper is updated. This callback is not called
13027   * on the initialization/creation of the popper, but only on subsequent
13028   * updates.<br />
13029   * By default, it is set to no-op.<br />
13030   * Access Popper.js instance with `data.instance`.
13031   * @prop {onUpdate}
13032   */
13033  onUpdate: function onUpdate() {},
13034
13035  /**
13036   * List of modifiers used to modify the offsets before they are applied to the popper.
13037   * They provide most of the functionalities of Popper.js.
13038   * @prop {modifiers}
13039   */
13040  modifiers: modifiers
13041};
13042
13043/**
13044 * @callback onCreate
13045 * @param {dataObject} data
13046 */
13047
13048/**
13049 * @callback onUpdate
13050 * @param {dataObject} data
13051 */
13052
13053// Utils
13054// Methods
13055var Popper = function () {
13056  /**
13057   * Creates a new Popper.js instance.
13058   * @class Popper
13059   * @param {Element|referenceObject} reference - The reference element used to position the popper
13060   * @param {Element} popper - The HTML / XML element used as the popper
13061   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
13062   * @return {Object} instance - The generated Popper.js instance
13063   */
13064  function Popper(reference, popper) {
13065    var _this = this;
13066
13067    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
13068    classCallCheck(this, Popper);
13069
13070    this.scheduleUpdate = function () {
13071      return requestAnimationFrame(_this.update);
13072    };
13073
13074    // make update() debounced, so that it only runs at most once-per-tick
13075    this.update = debounce(this.update.bind(this));
13076
13077    // with {} we create a new object with the options inside it
13078    this.options = _extends({}, Popper.Defaults, options);
13079
13080    // init state
13081    this.state = {
13082      isDestroyed: false,
13083      isCreated: false,
13084      scrollParents: []
13085    };
13086
13087    // get reference and popper elements (allow jQuery wrappers)
13088    this.reference = reference && reference.jquery ? reference[0] : reference;
13089    this.popper = popper && popper.jquery ? popper[0] : popper;
13090
13091    // Deep merge modifiers options
13092    this.options.modifiers = {};
13093    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
13094      _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
13095    });
13096
13097    // Refactoring modifiers' list (Object => Array)
13098    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
13099      return _extends({
13100        name: name
13101      }, _this.options.modifiers[name]);
13102    })
13103    // sort the modifiers by order
13104    .sort(function (a, b) {
13105      return a.order - b.order;
13106    });
13107
13108    // modifiers have the ability to execute arbitrary code when Popper.js get inited
13109    // such code is executed in the same order of its modifier
13110    // they could add new properties to their options configuration
13111    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
13112    this.modifiers.forEach(function (modifierOptions) {
13113      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
13114        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
13115      }
13116    });
13117
13118    // fire the first update to position the popper in the right place
13119    this.update();
13120
13121    var eventsEnabled = this.options.eventsEnabled;
13122    if (eventsEnabled) {
13123      // setup event listeners, they will take care of update the position in specific situations
13124      this.enableEventListeners();
13125    }
13126
13127    this.state.eventsEnabled = eventsEnabled;
13128  }
13129
13130  // We can't use class properties because they don't get listed in the
13131  // class prototype and break stuff like Sinon stubs
13132
13133
13134  createClass(Popper, [{
13135    key: 'update',
13136    value: function update$$1() {
13137      return update.call(this);
13138    }
13139  }, {
13140    key: 'destroy',
13141    value: function destroy$$1() {
13142      return destroy.call(this);
13143    }
13144  }, {
13145    key: 'enableEventListeners',
13146    value: function enableEventListeners$$1() {
13147      return enableEventListeners.call(this);
13148    }
13149  }, {
13150    key: 'disableEventListeners',
13151    value: function disableEventListeners$$1() {
13152      return disableEventListeners.call(this);
13153    }
13154
13155    /**
13156     * Schedules an update. It will run on the next UI update available.
13157     * @method scheduleUpdate
13158     * @memberof Popper
13159     */
13160
13161
13162    /**
13163     * Collection of utilities useful when writing custom modifiers.
13164     * Starting from version 1.7, this method is available only if you
13165     * include `popper-utils.js` before `popper.js`.
13166     *
13167     * **DEPRECATION**: This way to access PopperUtils is deprecated
13168     * and will be removed in v2! Use the PopperUtils module directly instead.
13169     * Due to the high instability of the methods contained in Utils, we can't
13170     * guarantee them to follow semver. Use them at your own risk!
13171     * @static
13172     * @private
13173     * @type {Object}
13174     * @deprecated since version 1.8
13175     * @member Utils
13176     * @memberof Popper
13177     */
13178
13179  }]);
13180  return Popper;
13181}();
13182
13183/**
13184 * The `referenceObject` is an object that provides an interface compatible with Popper.js
13185 * and lets you use it as replacement of a real DOM node.<br />
13186 * You can use this method to position a popper relatively to a set of coordinates
13187 * in case you don't have a DOM node to use as reference.
13188 *
13189 * ```
13190 * new Popper(referenceObject, popperNode);
13191 * ```
13192 *
13193 * NB: This feature isn't supported in Internet Explorer 10.
13194 * @name referenceObject
13195 * @property {Function} data.getBoundingClientRect
13196 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
13197 * @property {number} data.clientWidth
13198 * An ES6 getter that will return the width of the virtual reference element.
13199 * @property {number} data.clientHeight
13200 * An ES6 getter that will return the height of the virtual reference element.
13201 */
13202
13203
13204Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
13205Popper.placements = placements;
13206Popper.Defaults = Defaults;
13207
13208return Popper;
13209
13210})));
13211//# sourceMappingURL=popper.js.map
13212
13213/*!
13214  * Bootstrap v4.3.1 (https://getbootstrap.com/)
13215  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
13216  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13217  */
13218!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function s(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function l(o){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},e=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),e.forEach(function(t){var e,n,i;e=o,i=r[n=t],n in e?Object.defineProperty(e,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[n]=i})}return o}g=g&&g.hasOwnProperty("default")?g.default:g,u=u&&u.hasOwnProperty("default")?u.default:u;var e="transitionend";function n(t){var e=this,n=!1;return g(this).one(_.TRANSITION_END,function(){n=!0}),setTimeout(function(){n||_.triggerTransitionEnd(e)},t),this}var _={TRANSITION_END:"bsTransitionEnd",getUID:function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=g(t).css("transition-duration"),n=g(t).css("transition-delay"),i=parseFloat(e),o=parseFloat(n);return i||o?(e=e.split(",")[0],n=n.split(",")[0],1e3*(parseFloat(e)+parseFloat(n))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){g(t).trigger(e)},supportsTransitionEnd:function(){return Boolean(e)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],r=e[i],s=r&&_.isElement(r)?"element":(a=r,{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(o).test(s))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"!=typeof t.getRootNode)return t instanceof ShadowRoot?t:t.parentNode?_.findShadowRoot(t.parentNode):null;var e=t.getRootNode();return e instanceof ShadowRoot?e:null}};g.fn.emulateTransitionEnd=n,g.event.special[_.TRANSITION_END]={bindType:e,delegateType:e,handle:function(t){if(g(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var o="alert",r="bs.alert",a="."+r,c=g.fn[o],h={CLOSE:"close"+a,CLOSED:"closed"+a,CLICK_DATA_API:"click"+a+".data-api"},f="alert",d="fade",m="show",p=function(){function i(t){this._element=t}var t=i.prototype;return t.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)}
13218,t.dispose=function(){g.removeData(this._element,r),this._element=null},t._getRootElement=function(t){var e=_.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=g(t).closest("."+f)[0]),n},t._triggerCloseEvent=function(t){var e=g.Event(h.CLOSE);return g(t).trigger(e),e},t._removeElement=function(e){var n=this;if(g(e).removeClass(m),g(e).hasClass(d)){var t=_.getTransitionDurationFromElement(e);g(e).one(_.TRANSITION_END,function(t){return n._destroyElement(e,t)}).emulateTransitionEnd(t)}else this._destroyElement(e)},t._destroyElement=function(t){g(t).detach().trigger(h.CLOSED).remove()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(r);e||(e=new i(this),t.data(r,e)),"close"===n&&e[n](this)})},i._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();g(document).on(h.CLICK_DATA_API,'[data-dismiss="alert"]',p._handleDismiss(new p)),g.fn[o]=p._jQueryInterface,g.fn[o].Constructor=p,g.fn[o].noConflict=function(){return g.fn[o]=c,p._jQueryInterface};var v="button",y="bs.button",E="."+y,C=".data-api",T=g.fn[v],S="active",b="btn",I="focus",D='[data-toggle^="button"]',w='[data-toggle="buttons"]',A='input:not([type="hidden"])',N=".active",O=".btn",k={CLICK_DATA_API:"click"+E+C,FOCUS_BLUR_DATA_API:"focus"+E+C+" blur"+E+C},P=function(){function n(t){this._element=t}var t=n.prototype;return t.toggle=function(){var t=!0,e=!0,n=g(this._element).closest(w)[0];if(n){var i=this._element.querySelector(A);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(S))t=!1;else{var o=n.querySelector(N);o&&g(o).removeClass(S)}if(t){if(i.hasAttribute("disabled")||n.hasAttribute("disabled")||i.classList.contains("disabled")||n.classList.contains("disabled"))return;i.checked=!this._element.classList.contains(S),g(i).trigger("change")}i.focus(),e=!1}}e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(S)),t&&g(this._element).toggleClass(S)},t.dispose=function(){g.removeData(this._element,y),this._element=null},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(y);t||(t=new n(this),g(this).data(y,t)),"toggle"===e&&t[e]()})},s(n,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),n}();g(document).on(k.CLICK_DATA_API,D,function(t){t.preventDefault();var e=t.target;g(e).hasClass(b)||(e=g(e).closest(O)),P._jQueryInterface.call(g(e),"toggle")}).on(k.FOCUS_BLUR_DATA_API,D,function(t){var e=g(t.target).closest(O)[0];g(e).toggleClass(I,/^focus(in)?$/.test(t.type))}),g.fn[v]=P._jQueryInterface,g.fn[v].Constructor=P,g.fn[v].noConflict=function(){return g.fn[v]=T,P._jQueryInterface};var L="carousel",j="bs.carousel",H="."+j,R=".data-api",x=g.fn[L],F={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},U={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},W="next",q="prev",M="left",K="right",Q={SLIDE:"slide"+H,SLID:"slid"+H,KEYDOWN:"keydown"+H,MOUSEENTER:"mouseenter"+H,MOUSELEAVE:"mouseleave"+H,TOUCHSTART:"touchstart"+H,TOUCHMOVE:"touchmove"+H,TOUCHEND:"touchend"+H,POINTERDOWN:"pointerdown"+H,POINTERUP:"pointerup"+H,DRAG_START:"dragstart"+H,LOAD_DATA_API:"load"+H+R,CLICK_DATA_API:"click"+H+R},B="carousel",V="active",Y="slide",z="carousel-item-right",X="carousel-item-left",$="carousel-item-next",G="carousel-item-prev",J="pointer-event",Z=".active",tt=".active.carousel-item",et=".carousel-item",nt=".carousel-item img",it=".carousel-item-next, .carousel-item-prev",ot=".carousel-indicators",rt="[data-slide], [data-slide-to]",st='[data-ride="carousel"]',at={TOUCH:"touch",PEN:"pen"},lt=function(){function r(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(ot),this._touchSupported="ontouchstart"in document.documentElement||0<navigator.maxTouchPoints,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var t=r.prototype;return t.next=function(){this._isSliding||this._slide(W)},t.nextWhenVisible=function(){!document.hidden&&g(this._element).is(":visible")&&"hidden"
13218!==g(this._element).css("visibility")&&this.next()},t.prev=function(){this._isSliding||this._slide(q)},t.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(it)&&(_.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},t.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},t.to=function(t){var e=this;this._activeElement=this._element.querySelector(tt);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=n<t?W:q;this._slide(i,this._items[t])}},t.dispose=function(){g(this._element).off(H),g.removeData(this._element,j),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},t._getConfig=function(t){return t=l({},F,t),_.typeCheckConfig(L,t,U),t},t._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;0<e&&this.prev(),e<0&&this.next()}},t._addEventListeners=function(){var e=this;this._config.keyboard&&g(this._element).on(Q.KEYDOWN,function(t){return e._keydown(t)}),"hover"===this._config.pause&&g(this._element).on(Q.MOUSEENTER,function(t){return e.pause(t)}).on(Q.MOUSELEAVE,function(t){return e.cycle(t)}),this._config.touch&&this._addTouchEventListeners()},t._addTouchEventListeners=function(){var n=this;if(this._touchSupported){var e=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]?n.touchStartX=t.originalEvent.clientX:n._pointerEvent||(n.touchStartX=t.originalEvent.touches[0].clientX)},i=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]&&(n.touchDeltaX=t.originalEvent.clientX-n.touchStartX),n._handleSwipe(),"hover"===n._config.pause&&(n.pause(),n.touchTimeout&&clearTimeout(n.touchTimeout),n.touchTimeout=setTimeout(function(t){return n.cycle(t)},500+n._config.interval))};g(this._element.querySelectorAll(nt)).on(Q.DRAG_START,function(t){return t.preventDefault()}),this._pointerEvent?(g(this._element).on(Q.POINTERDOWN,function(t){return e(t)}),g(this._element).on(Q.POINTERUP,function(t){return i(t)}),this._element.classList.add(J)):(g(this._element).on(Q.TOUCHSTART,function(t){return e(t)}),g(this._element).on(Q.TOUCHMOVE,function(t){var e;(e=t).originalEvent.touches&&1<e.originalEvent.touches.length?n.touchDeltaX=0:n.touchDeltaX=e.originalEvent.touches[0].clientX-n.touchStartX}),g(this._element).on(Q.TOUCHEND,function(t){return i(t)}))}},t._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},t._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(et)):[],this._items.indexOf(t)},t._getItemByDirection=function(t,e){var n=t===W,i=t===q,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+(t===q?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},t._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(tt)),o=g.Event(Q.SLIDE,{relatedTarget:t,direction:e,from:i,to:n});return g(this._element).trigger(o),o},t._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(Z));g(e).removeClass(V);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&g(n).addClass(V)}},t._slide=function(t,e){var n,i,o,r=this,s=this._element.querySelector(tt),a=this._getItemIndex(s),l=e||s&&this._getItemByDirection(t,s),c=this._getItemIndex(l),h=Boolean(this._interval);if(o=t===W?(n=X,i=$,M):(n=z,i=G,K),l&&g(l).hasClass(V))this._isSliding=!1;else if(!this._triggerSlideEvent(l,o).isDefaultPrevented()&&s&&l){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(l);var u=g.Event(Q.SLID,{relatedTarget:l,direction:o,from:a,to:c});if(g(this._element).hasClass(Y)){g(l).addClass(i),_.reflow(l),g(s).addClass(n),g(l).addClass(n);var f=parseInt(l.getAttribute("data-interval"),10);this._config.interval=f?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,f):this._config.defaultInterval||this._config.interval;var d=_.getTransitionDurationFromElement(s);g(s).one(_.TRANSITION_END,function(){g(l).removeClass(n+" "+i).addClass(V),g(s).removeClass(V+" "+i+" "+n),r._isSliding=!1,setTimeout(function(){return g(r._element).trigger(u)},0)}).emulateTransitionEnd(d)}else g(s).removeClass(V),g(l).addClass(V),this._isSliding=!1,g(this._element).trigger(u);h&&this.cycle()}},r._jQueryInterface=function(i){return this.each(function(){var t=g(this).data(j),e=l({},F,g(this).data());"object"==typeof i&&(e=l({},e,i));var n="string"==typeof i?i:e.slide;if(t||(t=new r(this,e),g(this).data(j,t)),"number"==typeof i)t.to(i);else if("string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method n
13218amed "'+n+'"');t[n]()}else e.interval&&e.ride&&(t.pause(),t.cycle())})},r._dataApiClickHandler=function(t){var e=_.getSelectorFromElement(this);if(e){var n=g(e)[0];if(n&&g(n).hasClass(B)){var i=l({},g(n).data(),g(this).data()),o=this.getAttribute("data-slide-to");o&&(i.interval=!1),r._jQueryInterface.call(g(n),i),o&&g(n).data(j).to(o),t.preventDefault()}}},s(r,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return F}}]),r}();g(document).on(Q.CLICK_DATA_API,rt,lt._dataApiClickHandler),g(window).on(Q.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(st)),e=0,n=t.length;e<n;e++){var i=g(t[e]);lt._jQueryInterface.call(i,i.data())}}),g.fn[L]=lt._jQueryInterface,g.fn[L].Constructor=lt,g.fn[L].noConflict=function(){return g.fn[L]=x,lt._jQueryInterface};var ct="collapse",ht="bs.collapse",ut="."+ht,ft=g.fn[ct],dt={toggle:!0,parent:""},gt={toggle:"boolean",parent:"(string|element)"},_t={SHOW:"show"+ut,SHOWN:"shown"+ut,HIDE:"hide"+ut,HIDDEN:"hidden"+ut,CLICK_DATA_API:"click"+ut+".data-api"},mt="show",pt="collapse",vt="collapsing",yt="collapsed",Et="width",Ct="height",Tt=".show, .collapsing",St='[data-toggle="collapse"]',bt=function(){function a(e,t){this._isTransitioning=!1,this._element=e,this._config=this._getConfig(t),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'));for(var n=[].slice.call(document.querySelectorAll(St)),i=0,o=n.length;i<o;i++){var r=n[i],s=_.getSelectorFromElement(r),a=[].slice.call(document.querySelectorAll(s)).filter(function(t){return t===e});null!==s&&0<a.length&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var t=a.prototype;return t.toggle=function(){g(this._element).hasClass(mt)?this.hide():this.show()},t.show=function(){var t,e,n=this;if(!this._isTransitioning&&!g(this._element).hasClass(mt)&&(this._parent&&0===(t=[].slice.call(this._parent.querySelectorAll(Tt)).filter(function(t){return"string"==typeof n._config.parent?t.getAttribute("data-parent")===n._config.parent:t.classList.contains(pt)})).length&&(t=null),!(t&&(e=g(t).not(this._selector).data(ht))&&e._isTransitioning))){var i=g.Event(_t.SHOW);if(g(this._element).trigger(i),!i.isDefaultPrevented()){t&&(a._jQueryInterface.call(g(t).not(this._selector),"hide"),e||g(t).data(ht,null));var o=this._getDimension();g(this._element).removeClass(pt).addClass(vt),this._element.style[o]=0,this._triggerArray.length&&g(this._triggerArray).removeClass(yt).attr("aria-expanded",!0),this.setTransitioning(!0);var r="scroll"+(o[0].toUpperCase()+o.slice(1)),s=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){g(n._element).removeClass(vt).addClass(pt).addClass(mt),n._element.style[o]="",n.setTransitioning(!1),g(n._element).trigger(_t.SHOWN)}).emulateTransitionEnd(s),this._element.style[o]=this._element[r]+"px"}}},t.hide=function(){var t=this;if(!this._isTransitioning&&g(this._element).hasClass(mt)){var e=g.Event(_t.HIDE);if(g(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",_.reflow(this._element),g(this._element).addClass(vt).removeClass(pt).removeClass(mt);var i=this._triggerArray.length;if(0<i)for(var o=0;o<i;o++){var r=this._triggerArray[o],s=_.getSelectorFromElement(r);if(null!==s)g([].slice.call(document.querySelectorAll(s))).hasClass(mt)||g(r).addClass(yt).attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var a=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){t.setTransitioning(!1),g(t._element).removeClass(vt).addClass(pt).trigger(_t.HIDDEN)}).emulateTransitionEnd(a)}}},t.setTransitioning=function(t){this._isTransitioning=t},t.dispose=function(){g.removeData(this._element,ht),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},t._getConfig=function(t){return(t=l({},dt,t)).toggle=Boolean(t.toggle),_.typeCheckConfig(ct,t,gt),t},t._getDimension=function(){return g(this._element).hasClass(Et)?Et:Ct},t._getParent=function(){var t,n=this;_.isElement(this._config.parent)?(t=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(t=this._config.parent[0])):t=document.querySelector(this._config.parent);var e='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',i=[].slice.call(t.querySelectorAll(e));return g(i).each(function(t,e){n._addAriaAndCollapsedClass(a._getTargetFromElement(e),[e])}),t},t._addAriaAndCollapsedClass=function(t,e){var n=g(t).hasClass(mt);e.length&&g(e).toggleClass(yt,!n).attr("aria-expanded",n)},a._getTargetFromElement=function(t){var e=_.getSelectorFromElement(t);return e?document.querySelector(e):null},a._jQueryInterface=function(i){return this.each(function(){var t=g(this),e=t.data(ht),n=l({},dt,t.data(),"object"==typeof i&&i?i:{});if(!e&&n.toggle&&/show|hide/.test(i)&&(n.toggle=!1),e||(e=new a(this,n),t.data(ht,e)),"string"==typeof i){if("undefined"==typeof e[i])throw new TypeError('No method n
13218amed "'+i+'"');e[i]()}})},s(a,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return dt}}]),a}();g(document).on(_t.CLICK_DATA_API,St,function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=g(this),e=_.getSelectorFromElement(this),i=[].slice.call(document.querySelectorAll(e));g(i).each(function(){var t=g(this),e=t.data(ht)?"toggle":n.data();bt._jQueryInterface.call(t,e)})}),g.fn[ct]=bt._jQueryInterface,g.fn[ct].Constructor=bt,g.fn[ct].noConflict=function(){return g.fn[ct]=ft,bt._jQueryInterface};var It="dropdown",Dt="bs.dropdown",wt="."+Dt,At=".data-api",Nt=g.fn[It],Ot=new RegExp("38|40|27"),kt={HIDE:"hide"+wt,HIDDEN:"hidden"+wt,SHOW:"show"+wt,SHOWN:"shown"+wt,CLICK:"click"+wt,CLICK_DATA_API:"click"+wt+At,KEYDOWN_DATA_API:"keydown"+wt+At,KEYUP_DATA_API:"keyup"+wt+At},Pt="disabled",Lt="show",jt="dropup",Ht="dropright",Rt="dropleft",xt="dropdown-menu-right",Ft="position-static",Ut='[data-toggle="dropdown"]',Wt=".dropdown form",qt=".dropdown-menu",Mt=".navbar-nav",Kt=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Qt="top-start",Bt="top-end",Vt="bottom-start",Yt="bottom-end",zt="right-start",Xt="left-start",$t={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic"},Gt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string"},Jt=function(){function c(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var t=c.prototype;return t.toggle=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)){var t=c._getParentFromElement(this._element),e=g(this._menu).hasClass(Lt);if(c._clearMenus(),!e){var n={relatedTarget:this._element},i=g.Event(kt.SHOW,n);if(g(t).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar){if("undefined"==typeof u)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var o=this._element;"parent"===this._config.reference?o=t:_.isElement(this._config.reference)&&(o=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(o=this._config.reference[0])),"scrollParent"!==this._config.boundary&&g(t).addClass(Ft),this._popper=new u(o,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===g(t).closest(Mt).length&&g(document.body).children().on("mouseover",null,g.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),g(this._menu).toggleClass(Lt),g(t).toggleClass(Lt).trigger(g.Event(kt.SHOWN,n))}}}},t.show=function(){if(!(this._element.disabled||g(this._element).hasClass(Pt)||g(this._menu).hasClass(Lt))){var t={relatedTarget:this._element},e=g.Event(kt.SHOW,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.SHOWN,t)))}},t.hide=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)&&g(this._menu).hasClass(Lt)){var t={relatedTarget:this._element},e=g.Event(kt.HIDE,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.HIDDEN,t)))}},t.dispose=function(){g.removeData(this._element,Dt),g(this._element).off(wt),this._element=null,(this._menu=null)!==this._popper&&(this._popper.destroy(),this._popper=null)},t.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},t._addEventListeners=function(){var e=this;g(this._element).on(kt.CLICK,function(t){t.preventDefault(),t.stopPropagation(),e.toggle()})},t._getConfig=function(t){return t=l({},this.constructor.Default,g(this._element).data(),t),_.typeCheckConfig(It,t,this.constructor.DefaultType),t},t._getMenuElement=function(){if(!this._menu){var t=c._getParentFromElement(this._element);t&&(this._menu=t.querySelector(qt))}return this._menu},t._getPlacement=function(){var t=g(this._element.parentNode),e=Vt;return t.hasClass(jt)?(e=Qt,g(this._menu).hasClass(xt)&&(e=Bt)):t.hasClass(Ht)?e=zt:t.hasClass(Rt)?e=Xt:g(this._menu).hasClass(xt)&&(e=Yt),e},t._detectNavbar=function(){return 0<g(this._element).closest(".
13218navbar").length},t._getOffset=function(){var e=this,t={};return"function"==typeof this._config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e._config.offset(t.offsets,e._element)||{}),t}:t.offset=this._config.offset,t},t._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),t},c._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(Dt);if(t||(t=new c(this,"object"==typeof e?e:null),g(this).data(Dt,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},c._clearMenus=function(t){if(!t||3!==t.which&&("keyup"!==t.type||9===t.which))for(var e=[].slice.call(document.querySelectorAll(Ut)),n=0,i=e.length;n<i;n++){var o=c._getParentFromElement(e[n]),r=g(e[n]).data(Dt),s={relatedTarget:e[n]};if(t&&"click"===t.type&&(s.clickEvent=t),r){var a=r._menu;if(g(o).hasClass(Lt)&&!(t&&("click"===t.type&&/input|textarea/i.test(t.target.tagName)||"keyup"===t.type&&9===t.which)&&g.contains(o,t.target))){var l=g.Event(kt.HIDE,s);g(o).trigger(l),l.isDefaultPrevented()||("ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),e[n].setAttribute("aria-expanded","false"),g(a).removeClass(Lt),g(o).removeClass(Lt).trigger(g.Event(kt.HIDDEN,s)))}}}},c._getParentFromElement=function(t){var e,n=_.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},c._dataApiKeydownHandler=function(t){if((/input|textarea/i.test(t.target.tagName)?!(32===t.which||27!==t.which&&(40!==t.which&&38!==t.which||g(t.target).closest(qt).length)):Ot.test(t.which))&&(t.preventDefault(),t.stopPropagation(),!this.disabled&&!g(this).hasClass(Pt))){var e=c._getParentFromElement(this),n=g(e).hasClass(Lt);if(n&&(!n||27!==t.which&&32!==t.which)){var i=[].slice.call(e.querySelectorAll(Kt));if(0!==i.length){var o=i.indexOf(t.target);38===t.which&&0<o&&o--,40===t.which&&o<i.length-1&&o++,o<0&&(o=0),i[o].focus()}}else{if(27===t.which){var r=e.querySelector(Ut);g(r).trigger("focus")}g(this).trigger("click")}}},s(c,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return $t}},{key:"DefaultType",get:function(){return Gt}}]),c}();g(document).on(kt.KEYDOWN_DATA_API,Ut,Jt._dataApiKeydownHandler).on(kt.KEYDOWN_DATA_API,qt,Jt._dataApiKeydownHandler).on(kt.CLICK_DATA_API+" "+kt.KEYUP_DATA_API,Jt._clearMenus).on(kt.CLICK_DATA_API,Ut,function(t){t.preventDefault(),t.stopPropagation(),Jt._jQueryInterface.call(g(this),"toggle")}).on(kt.CLICK_DATA_API,Wt,function(t){t.stopPropagation()}),g.fn[It]=Jt._jQueryInterface,g.fn[It].Constructor=Jt,g.fn[It].noConflict=function(){return g.fn[It]=Nt,Jt._jQueryInterface};var Zt="modal",te="bs.modal",ee="."+te,ne=g.fn[Zt],ie={backdrop:!0,keyboard:!0,focus:!0,show:!0},oe={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},re={HIDE:"hide"+ee,HIDDEN:"hidden"+ee,SHOW:"show"+ee,SHOWN:"shown"+ee,FOCUSIN:"focusin"+ee,RESIZE:"resize"+ee,CLICK_DISMISS:"click.dismiss"+ee,KEYDOWN_DISMISS:"keydown.dismiss"+ee,MOUSEUP_DISMISS:"mouseup.dismiss"+ee,MOUSEDOWN_DISMISS:"mousedown.dismiss"+ee,CLICK_DATA_API:"click"+ee+".data-api"},se="modal-dialog-scrollable",ae="modal-scrollbar-measure",le="modal-backdrop",ce="modal-open",he="fade",ue="show",fe=".modal-dialog",de=".modal-body",ge='[data-toggle="modal"]',_e='[data-dismiss="modal"]',me=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",pe=".sticky-top",ve=function(){function o(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(fe),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var t=o.prototype;return t.toggle=function(t){return this._isShown?this.hide():this.show(t)},t.show=function(t){var e=this;if(!this._isShown&&!this._isTransitioning){g(this._element).hasClass(he)&&(this._isTransitioning=!0);var n=g.Event(re.SHOW,{relatedTarget:t});g(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),g(this._element).on(re.CLICK_DISMISS,_e,function(t){return e.hide(t)}),g(this._dialog).on(re.MOUSEDOWN_DISMISS,function(){g(e._element).one(re.MOUSEUP_DISMISS,function(t){g(t.target).is(e._element)&&(e._ignoreBackdropClick=!0)})}),this._showBackdrop(function(){return e._showElement(t)}))}},t.hide=function(t){var e=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var n=g.Event(re.HIDE);if(g(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=g(this._element).hasClass(he);if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),g(document).off(re.FOCUSIN),g(this._element).removeClass(ue),g(this._element).off(re.CLICK_DISMISS),g(this._dialog).off(re.MOUSEDOWN_DISMISS),i){var o=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(t){return e._hideModal(t)}).emulateTransitionEnd(o)}else this._hideModal()}}},t.dispose=function(){[window,this._element,this._dialog].forEach(function(t){return g(t).off(ee)}),g(document).off(re.FOCUSIN),g.removeData(this._element,te),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},t.handleUpdate=function(){this._adjustDialog()},t._getConfig=function(t){return t=l({},ie,t),_.typeCheckConfig(Zt,t,oe),t},t._showElement=function(t){var e=this,n=g(this._element).hasClass(he);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),g(this._dialog).hasClass(se)?this._dialog.querySelector(de).scrollTop=0:this._element.scrollTop=0,n&&_.reflow(this._element),g(this._element).addClass(ue),this._config.focus&&this._enforceFocus();
13218var i=g.Event(re.SHOWN,{relatedTarget:t}),o=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,g(e._element).trigger(i)};if(n){var r=_.getTransitionDurationFromElement(this._dialog);g(this._dialog).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()},t._enforceFocus=function(){var e=this;g(document).off(re.FOCUSIN).on(re.FOCUSIN,function(t){document!==t.target&&e._element!==t.target&&0===g(e._element).has(t.target).length&&e._element.focus()})},t._setEscapeEvent=function(){var e=this;this._isShown&&this._config.keyboard?g(this._element).on(re.KEYDOWN_DISMISS,function(t){27===t.which&&(t.preventDefault(),e.hide())}):this._isShown||g(this._element).off(re.KEYDOWN_DISMISS)},t._setResizeEvent=function(){var e=this;this._isShown?g(window).on(re.RESIZE,function(t){return e.handleUpdate(t)}):g(window).off(re.RESIZE)},t._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop(function(){g(document.body).removeClass(ce),t._resetAdjustments(),t._resetScrollbar(),g(t._element).trigger(re.HIDDEN)})},t._removeBackdrop=function(){this._backdrop&&(g(this._backdrop).remove(),this._backdrop=null)},t._showBackdrop=function(t){var e=this,n=g(this._element).hasClass(he)?he:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=le,n&&this._backdrop.classList.add(n),g(this._backdrop).appendTo(document.body),g(this._element).on(re.CLICK_DISMISS,function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._element.focus():e.hide())}),n&&_.reflow(this._backdrop),g(this._backdrop).addClass(ue),!t)return;if(!n)return void t();var i=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){g(this._backdrop).removeClass(ue);var o=function(){e._removeBackdrop(),t&&t()};if(g(this._element).hasClass(he)){var r=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()}else t&&t()},t._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},t._setScrollbar=function(){var o=this;if(this._isBodyOverflowing){var t=[].slice.call(document.querySelectorAll(me)),e=[].slice.call(document.querySelectorAll(pe));g(t).each(function(t,e){var n=e.style.paddingRight,i=g(e).css("padding-right");g(e).data("padding-right",n).css("padding-right",parseFloat(i)+o._scrollbarWidth+"px")}),g(e).each(function(t,e){var n=e.style.marginRight,i=g(e).css("margin-right");g(e).data("margin-right",n).css("margin-right",parseFloat(i)-o._scrollbarWidth+"px")});var n=document.body.style.paddingRight,i=g(document.body).css("padding-right");g(document.body).data("padding-right",n).css("padding-right",parseFloat(i)+this._scrollbarWidth+"px")}g(document.body).addClass(ce)},t._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(me));g(t).each(function(t,e){var n=g(e).data("padding-right");g(e).removeData("padding-right"),e.style.paddingRight=n||""});var e=[].slice.call(document.querySelectorAll(""+pe));g(e).each(function(t,e){var n=g(e).data("margin-right");"undefined"!=typeof n&&g(e).css("margin-right",n).removeData("margin-right")});var n=g(document.body).data("padding-right");g(document.body).removeData("padding-right"),document.body.style.paddingRight=n||""},t._getScrollbarWidth=function(){var t=document.createElement("div");t.className=ae,document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},o._jQueryInterface=function(n,i){return this.each(function(){var t=g(this).data(te),e=l({},ie,g(this).data(),"object"==typeof n&&n?n:{});if(t||(t=new o(this,e),g(this).data(te,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method n
13218amed "'+n+'"');t[n](i)}else e.show&&t.show(i)})},s(o,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return ie}}]),o}();g(document).on(re.CLICK_DATA_API,ge,function(t){var e,n=this,i=_.getSelectorFromElement(this);i&&(e=document.querySelector(i));var o=g(e).data(te)?"toggle":l({},g(e).data(),g(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var r=g(e).one(re.SHOW,function(t){t.isDefaultPrevented()||r.one(re.HIDDEN,function(){g(n).is(":visible")&&n.focus()})});ve._jQueryInterface.call(g(e),o,this)}),g.fn[Zt]=ve._jQueryInterface,g.fn[Zt].Constructor=ve,g.fn[Zt].noConflict=function(){return g.fn[Zt]=ne,ve._jQueryInterface};var ye=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],Ee={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Ce=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,Te=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function Se(t,s,e){if(0===t.length)return t;if(e&&"function"==typeof e)return e(t);for(var n=(new window.DOMParser).parseFromString(t,"text/html"),a=Object.keys(s),l=[].slice.call(n.body.querySelectorAll("*")),i=function(t,e){var n=l[t],i=n.nodeName.toLowerCase();if(-1===a.indexOf(n.nodeName.toLowerCase()))return n.parentNode.removeChild(n),"continue";var o=[].slice.call(n.attributes),r=[].concat(s["*"]||[],s[i]||[]);o.forEach(function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===ye.indexOf(n)||Boolean(t.nodeValue.match(Ce)||t.nodeValue.match(Te));for(var i=e.filter(function(t){return t instanceof RegExp}),o=0,r=i.length;o<r;o++)if(n.match(i[o]))return!0;return!1})(t,r)||n.removeAttribute(t.nodeName)})},o=0,r=l.length;o<r;o++)i(o);return n.body.innerHTML}var be="tooltip",Ie="bs.tooltip",De="."+Ie,we=g.fn[be],Ae="bs-tooltip",Ne=new RegExp("(^|\\s)"+Ae+"\\S+","g"),Oe=["sanitize","whiteList","sanitizeFn"],ke={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object"},Pe={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Le={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We}
13218,preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method n
13218amed "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0<e.length&&t.removeClass(e.join(""))},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ye),e="object"==typeof n?n:null;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ye,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Je}},{key:"NAME",get:function(){return Ve}},{key:"DATA_KEY",get:function(){return Ye}},{key:"Event",get:function(){return rn}},{key:"EVENT_KEY",get:function(){return ze}},{key:"DefaultType",get:function(){return Ze}}]),i}(Be);g.fn[Ve]=sn._jQueryInterface,g.fn[Ve].Constructor=sn,g.fn[Ve].noConflict=function(){return g.fn[Ve]=Xe,sn._jQueryInterface};var an="scrollspy",ln="bs.scrollspy",cn="."+ln,hn=g.fn[an],un={offset:10,method:"auto",target:""},fn={offset:"number",method:"string",target:"(string|element)"},dn={ACTIVATE:"activate"+cn,SCROLL:"scroll"+cn,LOAD_DATA_API:"load"+cn+".data-api"},gn="dropdown-item",_n="active",mn='[data-spy="scroll"]',pn=".nav, .list-group",vn=".nav-link",yn=".nav-item",En=".list-group-item",Cn=".dropdown",Tn=".dropdown-item",Sn=".dropdown-toggle",bn="offset",In="position",Dn=function(){function n(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+vn+","+this._config.target+" "+En+","+this._config.target+" "+Tn,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,g(this._scrollElement).on(dn.SCROLL,function(t){return n._process(t)}),this.refresh(),this._process()}var t=n.prototype;return t.refresh=function(){var e=this,t=this._scrollElement===this._scrollElement.window?bn:In,o="auto"===this._config.method?t:this._config.method,r=o===In?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map(function(t){var e,n=_.getSelectorFromElement(t);if(n&&(e=document.querySelector(n)),e){var i=e.getBoundingClientRect();if(i.width||i.height)return[g(e)[o]().top+r,n]}return null}).filter(function(t){return t}).sort(function(t,e){return t[0]-e[0]}
13218).forEach(function(t){e._offsets.push(t[0]),e._targets.push(t[1])})},t.dispose=function(){g.removeData(this._element,ln),g(this._scrollElement).off(cn),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},t._getConfig=function(t){if("string"!=typeof(t=l({},un,"object"==typeof t&&t?t:{})).target){var e=g(t.target).attr("id");e||(e=_.getUID(an),g(t.target).attr("id",e)),t.target="#"+e}return _.typeCheckConfig(an,t,fn),t},t._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},t._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},t._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},t._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),n<=t){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&0<this._offsets[0])return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},t._activate=function(e){this._activeTarget=e,this._clear();var t=this._selector.split(",").map(function(t){return t+'[data-target="'+e+'"],'+t+'[href="'+e+'"]'}),n=g([].slice.call(document.querySelectorAll(t.join(","))));n.hasClass(gn)?(n.closest(Cn).find(Sn).addClass(_n),n.addClass(_n)):(n.addClass(_n),n.parents(pn).prev(vn+", "+En).addClass(_n),n.parents(pn).prev(yn).children(vn).addClass(_n)),g(this._scrollElement).trigger(dn.ACTIVATE,{relatedTarget:e})},t._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter(function(t){return t.classList.contains(_n)}).forEach(function(t){return t.classList.remove(_n)})},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(ln);if(t||(t=new n(this,"object"==typeof e&&e),g(this).data(ln,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},s(n,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return un}}]),n}();g(window).on(dn.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(mn)),e=t.length;e--;){var n=g(t[e]);Dn._jQueryInterface.call(n,n.data())}}),g.fn[an]=Dn._jQueryInterface,g.fn[an].Constructor=Dn,g.fn[an].noConflict=function(){return g.fn[an]=hn,Dn._jQueryInterface};var wn="bs.tab",An="."+wn,Nn=g.fn.tab,On={HIDE:"hide"+An,HIDDEN:"hidden"+An,SHOW:"show"+An,SHOWN:"shown"+An,CLICK_DATA_API:"click"+An+".data-api"},kn="dropdown-menu",Pn="active",Ln="disabled",jn="fade",Hn="show",Rn=".dropdown",xn=".nav, .list-group",Fn=".active",Un="> li > .active",Wn='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',qn=".dropdown-toggle",Mn="> .dropdown-menu .active",Kn=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&g(this._element).hasClass(Pn)||g(this._element).hasClass(Ln))){var t,i,e=g(this._element).closest(xn)[0],o=_.getSelectorFromElement(this._element);if(e){var r="UL"===e.nodeName||"OL"===e.nodeName?Un:Fn;i=(i=g.makeArray(g(e).find(r)))[i.length-1]}var s=g.Event(On.HIDE,{relatedTarget:this._element}),a=g.Event(On.SHOW,{relatedTarget:i});if(i&&g(i).trigger(s),g(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(t=document.querySelector(o)),this._activate(this._element,e);var l=function(){var t=g.Event(On.HIDDEN,{relatedTarget:n._element}),e=g.Event(On.SHOWN,{relatedTarget:i});g(i).trigger(t),g(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){g.removeData(this._element,wn),this._element=null},t._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?g(e).children(Fn):g(e).find(Un))[0],r=n&&o&&g(o).hasClass(jn),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=_.getTransitionDurationFromElement(o);g(o).removeClass(Hn).one(_.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},t._transitionComplete=function(t,e,n){if(e){g(e).removeClass(Pn);var i=g(e.parentNode).find(Mn)[0];i&&g(i).removeClass(Pn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(g(t).addClass(Pn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),_.reflow(t),t.classList.contains(jn)&&t.classList.add(Hn),t.parentNode&&g(t.parentNode).hasClass(kn)){var o=g(t).closest(Rn)[0];if(o){var r=[].slice.call(o.querySelectorAll(qn));g(r).addClass(Pn)}t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(wn);if(e||(e=new i(this),t.data(wn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method n
13218amed "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();g(document).on(On.CLICK_DATA_API,Wn,function(t){t.preventDefault(),Kn._jQueryInterface.call(g(this),"show")}),g.fn.tab=Kn._jQueryInterface,g.fn.tab.Constructor=Kn,g.fn.tab.noConflict=function(){return g.fn.tab=Nn,Kn._jQueryInterface};var Qn="toast",Bn="bs.toast",Vn="."+Bn,Yn=g.fn[Qn],zn={CLICK_DISMISS:"click.dismiss"+Vn,HIDE:"hide"+Vn,HIDDEN:"hidden"+Vn,SHOW:"show"+Vn,SHOWN:"shown"+Vn},Xn="fade",$n="hide",Gn="show",Jn="showing",Zn={animation:"boolean",autohide:"boolean",delay:"number"},ti={animation:!0,autohide:!0,delay:500},ei='[data-dismiss="toast"]',ni=function(){function i(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var t=i.prototype;return t.show=function(){var t=this;g(this._element).trigger(zn.SHOW),this._config.animation&&this._element.classList.add(Xn);var e=function(){t._element.classList.remove(Jn),t._element.classList.add(Gn),g(t._element).trigger(zn.SHOWN),t._config.autohide&&t.hide()};if(this._element.classList.remove($n),this._element.classList.add(Jn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},t.hide=function(t){var e=this;this._element.classList.contains(Gn)&&(g(this._element).trigger(zn.HIDE),t?this._close():this._timeout=setTimeout(function(){e._close()},this._config.delay))},t.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(Gn)&&this._element.classList.remove(Gn),g(this._element).off(zn.CLICK_DISMISS),g.removeData(this._element,Bn),this._element=null,this._config=null},t._getConfig=function(t){return t=l({},ti,g(this._element).data(),"object"==typeof t&&t?t:{}),_.typeCheckConfig(Qn,t,this.constructor.DefaultType),t},t._setListeners=function(){var t=this;g(this._element).on(zn.CLICK_DISMISS,ei,function(){return t.hide(!0)})},t._close=function(){var t=this,e=function(){t._element.classList.add($n),g(t._element).trigger(zn.HIDDEN)};if(this._element.classList.remove(Gn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(Bn);if(e||(e=new i(this,"object"==typeof n&&n),t.data(Bn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"DefaultType",get:function(){return Zn}},{key:"Default",get:function(){return ti}}]),i}();g.fn[Qn]=ni._jQueryInterface,g.fn[Qn].Constructor=ni,g.fn[Qn].noConflict=function(){return g.fn[Qn]=Yn,ni._jQueryInterface},function(){if("undefined"==typeof g)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=g.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||4<=t[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),t.Util=_,t.Alert=p,t.Button=P,t.Carousel=lt,t.Collapse=bt,t.Dropdown=Jt,t.Modal=ve,t.Popover=sn,t.Scrollspy=Dn,t.Tab=Kn,t.Toast=ni,t.Tooltip=Be,Object.defineProperty(t,"__esModule",{value:!0})});
13219//# sourceMappingURL=bootstrap.min.js.map
13220/*!
13221 * JavaScript Cookie v2.2.0
13222 * https://github.com/js-cookie/js-cookie
13223 *
13224 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
13225 * Released under the MIT license
13226 */
13227;(function (factory) {
13228	var registeredInModuleLoader = false;
13229	if (typeof define === 'function' && define.amd) {
13230		define(factory);
13231		registeredInModuleLoader = true;
13232	}
13233	if (typeof exports === 'object') {
13234		module.exports = factory();
13235		registeredInModuleLoader = true;
13236	}
13237	if (!registeredInModuleLoader) {
13238		var OldCookies = window.Cookies;
13239		var api = window.Cookies = factory();
13240		api.noConflict = function () {
13241			window.Cookies = OldCookies;
13242			return api;
13243		};
13244	}
13245}(function () {
13246	function extend () {
13247		var i = 0;
13248		var result = {};
13249		for (; i < arguments.length; i++) {
13250			var attributes = arguments[ i ];
13251			for (var key in attributes) {
13252				result[key] = attributes[key];
13253			}
13254		}
13255		return result;
13256	}
13257
13258	function init (converter) {
13259		function api (key, value, attributes) {
13260			var result;
13261			if (typeof document === 'undefined') {
13262				return;
13263			}
13264
13265			// Write
13266
13267			if (arguments.length > 1) {
13268				attributes = extend({
13269					path: '/'
13270				}, api.defaults, attributes);
13271
13272				if (typeof attributes.expires === 'number') {
13273					var expires = new Date();
13274					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
13275					attributes.expires = expires;
13276				}
13277
13278				// We're using "expires" because "max-age" is not supported by IE
13279				attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
13280
13281				try {
13282					result = JSON.stringify(value);
13283					if (/^[\{\[]/.test(result)) {
13284						value = result;
13285					}
13286				} catch (e) {}
13287
13288				if (!converter.write) {
13289					value = encodeURIComponent(String(value))
13290						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
13291				} else {
13292					value = converter.write(value, key);
13293				}
13294
13295				key = encodeURIComponent(String(key));
13296				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
13297				key = key.replace(/[\(\)]/g, escape);
13298
13299				var stringifiedAttributes = '';
13300
13301				for (var attributeName in attributes) {
13302					if (!attributes[attributeName]) {
13303						continue;
13304					}
13305					stringifiedAttributes += '; ' + attributeName;
13306					if (attributes[attributeName] === true) {
13307						continue;
13308					}
13309					stringifiedAttributes += '=' + attributes[attributeName];
13310				}
13311				return (document.cookie = key + '=' + value + stringifiedAttributes);
13312			}
13313
13314			// Read
13315
13316			if (!key) {
13317				result = {};
13318			}
13319
13320			// To prevent the for loop in the first place assign an empty array
13321			// in case there are no cookies at all. Also prevents odd result when
13322			// calling "get()"
13323			var cookies = document.cookie ? document.cookie.split('; ') : [];
13324			var rdecode = /(%[0-9A-Z]{2})+/g;
13325			var i = 0;
13326
13327			for (; i < cookies.length; i++) {
13328				var parts = cookies[i].split('=');
13329				var cookie = parts.slice(1).join('=');
13330
13331				if (!this.json && cookie.charAt(0) === '"') {
13332					cookie = cookie.slice(1, -1);
13333				}
13334
13335				try {
13336					var name = parts[0].replace(rdecode, decodeURIComponent);
13337					cookie = converter.read ?
13338						converter.read(cookie, name) : converter(cookie, name) ||
13339						cookie.replace(rdecode, decodeURIComponent);
13340
13341					if (this.json) {
13342						try {
13343							cookie = JSON.parse(cookie);
13344						} catch (e) {}
13345					}
13346
13347					if (key === name) {
13348						result = cookie;
13349						break;
13350					}
13351
13352					if (!key) {
13353						result[name] = cookie;
13354					}
13355				} catch (e) {}
13356			}
13357
13358			return result;
13359		}
13360
13361		api.set = api;
13362		api.get = function (key) {
13363			return api.call(api, key);
13364		};
13365		api.getJSON = function () {
13366			return api.apply({
13367				json: true
13368			}, [].slice.call(arguments));
13369		};
13370		api.defaults = {};
13371
13372		api.remove = function (key, attributes) {
13373			api(key, '', extend(attributes, {
13374				expires: -1
13375			}));
13376		};
13377
13378		api.withConverter = init;
13379
13380		return api;
13381	}
13382
13383	return init(function () {});
13384}));
13385
vendor: 53,324 bytes, line 13386
13386!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function d(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Tt(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function v(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function p(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function k(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function S(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function D(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=S(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&D(e[s])!==D(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function b(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function x(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function C(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function H(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function R(e){var t,n,s={};for(n in e)m(e,n)&&(t=H(n))&&(s[t]=e[n]);return s}var U={};function F(e,t){U[e]=t}function L(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([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,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return L(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=b(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,n,s){oe[e]=b(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(he(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function he(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var de={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),h(n)&&(s=function(e,t){t[n]=D(e)}),t=0;t<e.length;t++)de[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,ve=4,pe=5,we=6,Me=7,ke=8;function Se(e){return De(e)?366:365}function De(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),C("year","y"),F("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):D(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return D(e)+(68<D(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(xe(this,t,e),c.updateOffset(this,n),this):be(this,t)}}function be(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function xe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&De(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?De(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),C("month","M"),F("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=D(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Ce="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var He="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Re(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=D(t);else if(!h(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Ue(e){return null!=e?(Re(this,e),c.updateOffset(this,!0),this):be(this,"Month")}var Fe=ae;var Le=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=he(s[t]),i[t]=he(i[t]);for(t=0;t<24;t++)r[t]=he(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t;if(e<100&&0<=e){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return a=o<=0?Se(r=e-1)+o:o>Se(e)?(r=e+1,o-Se(e)):(r=e,o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(Se(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),C("week","w"),C("isoWeek","W"),F("week",5),F("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=D(e)});function je(e,t){return e.slice(t,7).concat(e.slice(0,t))}I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),C("day","d"),C("weekday","e"),C("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=D(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var $e="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qe=ae;var Je=ae;var Be=ae;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=he(o[t]),u[t]=he(u[t]),l[t]=he(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Xe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)+L(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+L(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+L(this.minutes(),2)+L(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),C("hour","h"),F("hour",13),ue("a",et),ue("A",et),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=D(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=D(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i))});var tt,nt=Te("Hours",!0),st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{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"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d 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"},months:Ce,monthsShort:He,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){var t=null;if(!it[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=tt._abbr,require("./locale/"+e),ut(t)}catch(e){}return it[e]}function ut(e,t){var n;return e&&((n=l(t)?ht(e):lt(e,t))?tt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),tt._abbr}function lt(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ot(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new P(x(s,t)),rt[e]&&rt[e].forEach(function(e){lt(e.name,e.config)}),ut(e),it[e]}function ht(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return tt;if(!o(e)){if(t=ot(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=at(e[r]).split("-")).length,n=(n=at(e[r+1]))?n.split("-"):null;0<t;){if(s=ot(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return tt}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[ve]||0!==n[pe]||0!==n[we])?ge:n[ve]<0||59<n[ve]?ve:n[pe]<0||59<n[pe]?pe:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=ke),g(e).overflow=t),e}function ct(e,t,n){return null!=e?e:null!=t?t:n}function ft(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ct(t.GG,e._a[me],Ie(bt(),1,4).year),s=ct(t.W,1),((i=ct(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(bt(),r,a);n=ct(t.gg,e._a[me],l.year),s=ct(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ct(e._a[me],s[me]),(e._dayOfYear>Se(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[ve]&&0===e._a[pe]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var mt=/^\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)?)?$/,_t=/^\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)?)?$/,yt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["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/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],vt=[["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/]],pt=/^\/?Date\((\-?\d+)/i;function wt(e){var t,n,s,i,r,a,o=e._i,u=mt.exec(o)||_t.exec(o);if(u){for(g(e).iso=!0,t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[1])){i=gt[t][0],s=!1!==gt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=vt.length;t<n;t++)if(vt[t][1].exec(u[3])){r=(u[2]||" ")+vt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!yt.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),Yt(e)}else e._isValid=!1}var Mt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function kt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),He.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=Mt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var r=kt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function Yt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,h=l.length,d=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),d+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(de,a)&&de[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=h-d,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ft(e),dt(e)}else Dt(e);else wt(e)}function Ot(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||ht(e._l),null===r||void 0===a&&""===r?p({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),k(r)?new M(dt(r)):(d(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],Yt(t),v(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?Yt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):d(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(wt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ft(t)):u(n)?function(e){if(!e._d){var t=R(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ft(e)}}(t):h(n)?t._d=new Date(n):c.createFromInputFallback(t),v(e)||(e._d=null),e))}function Tt(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Ot(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function bt(e,t,n,s){return Tt(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:p()}),Pt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:p()});function Wt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return bt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Ct=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=R(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||t.isoWeek||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,h=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Ct,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Ct.length;++s)if(e[Ct[s]]){if(n)return!1;parseFloat(e[Ct[s]])!==D(e[Ct[s]])&&(n=!0)}return!0}(t),this._milliseconds=+h+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ht(),this._bubble()}function Rt(e){return e instanceof Ht}function Ut(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+L(~~(e/60),2)+n+L(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Nt(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Nt(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+D(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Gt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(k(e)||d(e)?e.valueOf():bt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):bt(e).local()}function Vt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Et(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var It=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,At=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function jt(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:h(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=It.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:D(a[ye])*n,h:D(a[ge])*n,m:D(a[ve])*n,s:D(a[pe])*n,ms:D(Ut(1e3*a[we]))*n}):(a=At.exec(e))?(n="-"===a[1]?-1:1,r={y:Zt(a[2],n),M:Zt(a[3],n),w:Zt(a[4],n),d:Zt(a[5],n),h:Zt(a[6],n),m:Zt(a[7],n),s:Zt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Gt(t,e),e.isBefore(t)?n=zt(e,t):((n=zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(bt(r.from),bt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function Zt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function zt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $t(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),qt(this,jt(e="string"==typeof e?+e:e,t),s),this}}function qt(e,t,n,s){var i=t._milliseconds,r=Ut(t._days),a=Ut(t._months);e.isValid()&&(s=null==s||s,a&&Re(e,be(e,"Month")+a*n),r&&xe(e,"Date",be(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}jt.fn=Ht.prototype,jt.invalid=function(){return jt(NaN)};var Jt=$t(1,"add"),Bt=$t(-1,"subtract");function Qt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Xt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ht(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Kt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function en(){return this._locale}var tn=126227808e5;function nn(e,t){return(e%t+t)%t}function sn(e,t,n){return e<100&&0<=e?new Date(e+400,t,n)-tn:new Date(e,t,n).valueOf()}function rn(e,t,n){return e<100&&0<=e?Date.UTC(e+400,t,n)-tn:Date.UTC(e,t,n)}function an(e,t){I(0,[e,e.length],0,t)}function on(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),an("gggg","weekYear"),an("ggggg","weekYear"),an("GGGG","isoWeekYear"),an("GGGGG","isoWeekYear"),C("weekYear","gg"),C("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=D(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),C("quarter","Q"),F("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(D(e)-1)}),I("D",["DD",2],"Do","date"),C("date","D"),F("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=D(e.match(B)[0])});var un=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),C("dayOfYear","DDD"),F("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=D(e)}),I("m",["mm",2],0,"minute"),C("minute","m"),F("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],ve);var ln=Te("Minutes",!1);I("s",["ss",2],0,"second"),C("second","s"),F("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],pe);var hn,dn=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),C("millisecond","ms"),F("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),hn="SSSS";hn.length<=9;hn+="S")ue(hn,ne);function cn(e,t){t[we]=D(1e3*("0."+e))}for(hn="S";hn.length<=9;hn+="S")ce(hn,cn);var fn=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var mn=M.prototype;function _n(e){return e}mn.add=Jt,mn.calendar=function(e,t){var n=e||bt(),s=Gt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(b(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,bt(n)))},mn.clone=function(){return new M(this)},mn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Gt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=H(t)){case"year":r=Qt(this,s)/12;break;case"month":r=Qt(this,s);break;case"quarter":r=Qt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:S(r)},mn.endOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=36e5-nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":t=this._d.valueOf(),t+=6e4-nn(t,6e4)-1;break;case"second":t=this._d.valueOf(),t+=1e3-nn(t,1e3)-1;break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},mn.from=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.fromNow=function(e){return this.from(bt(),e)},mn.to=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.toNow=function(e){return this.to(bt(),e)},mn.get=function(e){return b(this[e=H(e)])?this[e]():this},mn.invalidAt=function(){return g(this).overflow},mn.isAfter=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},mn.isBefore=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},mn.isBetween=function(e,t,n,s){var i=k(e)?e:bt(e),r=k(t)?t:bt(t);return!!(this.isValid()&&i.isValid()&&r.isValid())&&("("===(s=s||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===s[1]?this.isBefore(r,n):!this.isAfter(r,n))},mn.isSame=function(e,t){var n,s=k(e)?e:bt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},mn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},mn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},mn.isValid=function(){return v(this)},mn.lang=Kt,mn.locale=Xt,mn.localeData=en,mn.max=Pt,mn.min=xt,mn.parsingFlags=function(){return _({},g(this))},mn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:U[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=R(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(b(this[e=H(e)]))return this[e](t);return this},mn.startOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":t=this._d.valueOf(),t-=nn(t,6e4);break;case"second":t=this._d.valueOf(),t-=nn(t,1e3);break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.subtract=Bt,mn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},mn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},mn.toDate=function(){return new Date(this.valueOf())},mn.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):b(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},mn.toJSON=function(){return this.isValid()?this.toISOString():null},mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},mn.unix=function(){return Math.floor(this.valueOf()/1e3)},mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},mn.year=Oe,mn.isLeapYear=function(){return De(this.year())},mn.weekYear=function(e){return on.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},mn.isoWeekYear=function(e){return on.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},mn.quarter=mn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},mn.month=Ue,mn.daysInMonth=function(){return Pe(this.year(),this.month())},mn.week=mn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},mn.isoWeek=mn.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},mn.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},mn.isoWeeksInYear=function(){return Ae(this.year(),1,4)},mn.date=un,mn.day=mn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},mn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},mn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null==e)return this.day()||7;var t,n,s=(t=e,n=this.localeData(),"string"==typeof t?n.weekdaysParse(t)%7||7:isNaN(t)?null:t);return this.day(this.day()%7?s:s-7)},mn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},mn.hour=mn.hours=nt,mn.minute=mn.minutes=ln,mn.second=mn.seconds=dn,mn.millisecond=mn.milliseconds=fn,mn.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null==e)return this._isUTC?i:Vt(this);if("string"==typeof e){if(null===(e=Nt(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Vt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?qt(this,jt(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this},mn.utc=function(e){return this.utcOffset(0,e)},mn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Vt(this),"m")),this},mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Nt(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},mn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?bt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=Et,mn.isUTC=Et,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=n("dates accessor is deprecated. Use date instead.",un),mn.months=n("months accessor is deprecated. Use month instead",Ue),mn.years=n("years accessor is deprecated. Use year instead",Oe),mn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),mn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Ot(e))._a){var t=e._isUTC?y(e._a):bt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var yn=P.prototype;function gn(e,t,n,s){var i=ht(),r=y().set(s,t);return i[n](r,e)}function vn(e,t,n){if(h(e)&&(t=e,e=void 0),e=e||"",null!=t)return gn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=gn(e,s,n,"month");return i}function pn(e,t,n,s){t=("boolean"==typeof e?h(t)&&(n=t,t=void 0):(t=e,e=!1,h(n=t)&&(n=t,t=void 0)),t||"");var i,r=ht(),a=e?r._week.dow:0;if(null!=n)return gn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=gn(t,(i+a)%7,s,"day");return o}yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return b(s)?s.call(t,n):s},yn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},yn.invalidDate=function(){return this._invalidDate},yn.ordinal=function(e){return this._ordinal.replace("%d",e)},yn.preparse=_n,yn.postformat=_n,yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return b(i)?i(e,t,n,s):i.replace(/%d/i,e)},yn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return b(n)?n(t):n.replace(/%s/i,t)},yn.set=function(e){var t,n;for(n in e)b(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},yn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},yn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},yn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},yn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Le),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},yn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Fe),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},yn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},yn.firstDayOfYear=function(){return this._week.doy},yn.firstDayOfWeek=function(){return this._week.dow},yn.weekdays=function(e,t){var n=o(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?je(n,this._week.dow):e?n[e.day()]:n},yn.weekdaysMin=function(e){return!0===e?je(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},yn.weekdaysShort=function(e){return!0===e?je(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},yn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=qe),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Je),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Be),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},yn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ut("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===D(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ut),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",ht);var wn=Math.abs;function Mn(e,t,n,s){var i=jt(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function kn(e){return e<0?Math.floor(e):Math.ceil(e)}function Sn(e){return 4800*e/146097}function Dn(e){return 146097*e/4800}function Yn(e){return function(){return this.as(e)}}var On=Yn("ms"),Tn=Yn("s"),bn=Yn("m"),xn=Yn("h"),Pn=Yn("d"),Wn=Yn("w"),Cn=Yn("M"),Hn=Yn("Q"),Rn=Yn("y");function Un(e){return function(){return this.isValid()?this._data[e]:NaN}}var Fn=Un("milliseconds"),Ln=Un("seconds"),Nn=Un("minutes"),Gn=Un("hours"),Vn=Un("days"),En=Un("months"),In=Un("years");var An=Math.round,jn={ss:44,s:45,m:45,h:22,d:26,M:11};var Zn=Math.abs;function zn(e){return(0<e)-(e<0)||+e}function $n(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Zn(this._milliseconds)/1e3,s=Zn(this._days),i=Zn(this._months);t=S((e=S(n/60))/60),n%=60,e%=60;var r=S(i/12),a=i%=12,o=s,u=t,l=e,h=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var c=d<0?"-":"",f=zn(this._months)!==zn(d)?"-":"",m=zn(this._days)!==zn(d)?"-":"",_=zn(this._milliseconds)!==zn(d)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||h?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(h?_+h+"S":"")}var qn=Ht.prototype;return qn.isValid=function(){return this._isValid},qn.abs=function(){var e=this._data;return this._milliseconds=wn(this._milliseconds),this._days=wn(this._days),this._months=wn(this._months),e.milliseconds=wn(e.milliseconds),e.seconds=wn(e.seconds),e.minutes=wn(e.minutes),e.hours=wn(e.hours),e.months=wn(e.months),e.years=wn(e.years),this},qn.add=function(e,t){return Mn(this,e,t,1)},qn.subtract=function(e,t){return Mn(this,e,t,-1)},qn.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=H(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+Sn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Dn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},qn.asMilliseconds=On,qn.asSeconds=Tn,qn.asMinutes=bn,qn.asHours=xn,qn.asDays=Pn,qn.asWeeks=Wn,qn.asMonths=Cn,qn.asQuarters=Hn,qn.asYears=Rn,qn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12):NaN},qn._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*kn(Dn(o)+a),o=a=0),u.milliseconds=r%1e3,e=S(r/1e3),u.seconds=e%60,t=S(e/60),u.minutes=t%60,n=S(t/60),u.hours=n%24,o+=i=S(Sn(a+=S(n/24))),a-=kn(Dn(i)),s=S(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},qn.clone=function(){return jt(this)},qn.get=function(e){return e=H(e),this.isValid()?this[e+"s"]():NaN},qn.milliseconds=Fn,qn.seconds=Ln,qn.minutes=Nn,qn.hours=Gn,qn.days=Vn,qn.weeks=function(){return S(this.days()/7)},qn.months=En,qn.years=In,qn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,h,d,c=this.localeData(),f=(n=!e,s=c,i=jt(t=this).abs(),r=An(i.as("s")),a=An(i.as("m")),o=An(i.as("h")),u=An(i.as("d")),l=An(i.as("M")),h=An(i.as("y")),(d=r<=jn.ss&&["s",r]||r<jn.s&&["ss",r]||a<=1&&["m"]||a<jn.m&&["mm",a]||o<=1&&["h"]||o<jn.h&&["hh",o]||u<=1&&["d"]||u<jn.d&&["dd",u]||l<=1&&["M"]||l<jn.M&&["MM",l]||h<=1&&["y"]||["yy",h])[2]=n,d[3]=0<+t,d[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},qn.toISOString=$n,qn.toString=$n,qn.toJSON=$n,qn.locale=Xt,qn.localeData=en,qn.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",$n),qn.lang=Kt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(D(e))}),c.version="2.24.0",e=bt,c.fn=mn,c.min=function(){return Wt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Wt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return bt(1e3*e)},c.months=function(e,t){return vn(e,t,"months")},c.isDate=d,c.locale=ut,c.invalid=p,c.duration=jt,c.isMoment=k,c.weekdays=function(e,t,n){return pn(e,t,n,"weekdays")},c.parseZone=function(){return bt.apply(null,arguments).parseZone()},c.localeData=ht,c.isDuration=Rt,c.monthsShort=function(e,t){return vn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return pn(e,t,n,"weekdaysMin")},c.defineLocale=lt,c.updateLocale=function(e,t){if(null!=t){var n,s,i=st;null!=(s=ot(e))&&(i=s._config),(n=new P(t=x(i,t))).parentLocale=it[e],it[e]=n,ut(e)}else null!=it[e]&&(null!=it[e].parentLocale?it[e]=it[e].parentLocale:null!=it[e]&&delete it[e]);return it[e]},c.locales=function(){return s(it)},c.weekdaysShort=function(e,t,n){return pn(e,t,n,"weekdaysShort")},c.normalizeUnits=H,c.relativeTimeRounding=function(e){return void 0===e?An:"function"==typeof e&&(An=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==jn[e]&&(void 0===t?jn[e]:(jn[e]=t,"s"===e&&(jn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=mn,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},c});
13386
13387/*
13388 Copyright (C) Federico Zivolo 2019
13389 Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
13390 */(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b(require('popper.js')):'function'==typeof define&&define.amd?define(['popper.js'],b):a.Tooltip=b(a.Popper)})(this,function(a){'use strict';function b(a){return a&&'[object Function]'==={}.toString.call(a)}a=a&&a.hasOwnProperty('default')?a['default']:a;var c=function(a,b){if(!(a instanceof b))throw new TypeError('Cannot call a class as a function')},d=function(){function a(a,b){for(var c,d=0;d<b.length;d++)c=b[d],c.enumerable=c.enumerable||!1,c.configurable=!0,'value'in c&&(c.writable=!0),Object.defineProperty(a,c.key,c)}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),e=Object.assign||function(a){for(var b,c=1;c<arguments.length;c++)for(var d in b=arguments[c],b)Object.prototype.hasOwnProperty.call(b,d)&&(a[d]=b[d]);return a},f={container:!1,delay:0,html:!1,placement:'top',title:'',template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:'hover focus',offset:0,arrowSelector:'.tooltip-arrow, .tooltip__arrow',innerSelector:'.tooltip-inner, .tooltip__inner'},g=function(){function g(a,b){c(this,g),h.call(this),b=e({},f,b),a.jquery&&(a=a[0]),this.reference=a,this.options=b;var d='string'==typeof b.trigger?b.trigger.split(' ').filter(function(a){return-1!==['click','hover','focus'].indexOf(a)}):[];this._isOpen=!1,this._popperOptions={},this._setEventListeners(a,d,b)}return d(g,[{key:'_create',value:function(a,b,c,d){var e=window.document.createElement('div');e.innerHTML=b.trim();var f=e.childNodes[0];f.id='tooltip_'+Math.random().toString(36).substr(2,10),f.setAttribute('aria-hidden','false');var g=e.querySelector(this.options.innerSelector);return this._addTitleContent(a,c,d,g),f}},{key:'_addTitleContent',value:function(a,c,d,e){if(1===c.nodeType||11===c.nodeType)d&&e.appendChild(c);else if(b(c)){var f=c.call(a);d?e.innerHTML=f:e.textContent=f}else d?e.innerHTML=c:e.textContent=c}},{key:'_show',value:function(b,c){if(this._isOpen&&!this._isOpening)return this;if(this._isOpen=!0,this._tooltipNode)return this._tooltipNode.style.visibility='visible',this._tooltipNode.setAttribute('aria-hidden','false'),this.popperInstance.update(),this;var d=b.getAttribute('title')||c.title;if(!d)return this;var f=this._create(b,c.template,d,c.html);b.setAttribute('aria-describedby',f.id);var g=this._findContainer(c.container,b);return this._append(f,g),this._popperOptions=e({},c.popperOptions,{placement:c.placement}),this._popperOptions.modifiers=e({},this._popperOptions.modifiers,{arrow:e({},this._popperOptions.modifiers&&this._popperOptions.modifiers.arrow,{element:c.arrowSelector}),offset:e({},this._popperOptions.modifiers&&this._popperOptions.modifiers.offset,{offset:c.offset})}),c.boundariesElement&&(this._popperOptions.modifiers.preventOverflow={boundariesElement:c.boundariesElement}),this.popperInstance=new a(b,f,this._popperOptions),this._tooltipNode=f,this}},{key:'_hide',value:function(){return this._isOpen?(this._isOpen=!1,this._tooltipNode.style.visibility='hidden',this._tooltipNode.setAttribute('aria-hidden','true'),this):this}},{key:'_dispose',value:function(){var a=this;return this._events.forEach(function(b){var c=b.func,d=b.event;a.reference.removeEventListener(d,c)}),this._events=[],this._tooltipNode&&(this._hide(),this.popperInstance.destroy(),!this.popperInstance.options.removeOnDestroy&&(this._tooltipNode.parentNode.removeChild(this._tooltipNode),this._tooltipNode=null)),this}},{key:'_findContainer',value:function(a,b){return'string'==typeof a?a=window.document.querySelector(a):!1===a&&(a=b.parentNode),a}},{key:'_append',value:function(a,b){b.appendChild(a)}},{key:'_setEventListeners',value:function(a,b,c){var d=this,e=[],f=[];b.forEach(function(a){'hover'===a?(e.push('mouseenter'),f.push('mouseleave')):'focus'===a?(e.push('focus'),f.push('blur')):'click'===a?(e.push('click'),f.push('click')):void 0}),e.forEach(function(b){var e=function(b){!0===d._isOpening||(b.usedByTooltip=!0,d._scheduleShow(a,c.delay,c,b))};d._events.push({event:b,func:e}),a.addEventListener(b,e)}),f.forEach(function(b){var f=function(b){!0===b.usedByTooltip||d._scheduleHide(a,c.delay,c,b)};d._events.push({event:b,func:f}),a.addEventListener(b,f),'click'===b&&c.closeOnClickOutside&&document.addEventListener('mousedown',function(b){if(d._isOpening){var c=d.popperInstance.popper;a.contains(b.target)||c.contains(b.target)||f(b)}},!0)})}},{key:'_scheduleShow',value:function(a,b,c){var d=this;this._isOpening=!0;var e=b&&b.show||b||0;this._showTimeout=window.setTimeout(function(){return d._show(a,c)},e)}},{key:'_scheduleHide',value:function(a,b,c,d){var e=this;this._isOpening=!1;var f=b&&b.hide||b||0;window.clearTimeout(this._showTimeout),window.setTimeout(function(){if(!1!==e._isOpen&&document.body.contains(e._tooltipNode)){if('mouseleave'===d.type){var f=e._setTooltipNodeEvent(d,a,b,c);if(f)return}e._hide(a,c)}},f)}}
13390,{key:'_updateTitleContent',value:function(a){if('undefined'==typeof this._tooltipNode)return void('undefined'!=typeof this.options.title&&(this.options.title=a));var b=this._tooltipNode.querySelector(this.options.innerSelector);this._clearTitleContent(b,this.options.html,this.reference.getAttribute('title')||this.options.title),this._addTitleContent(this.reference,a,this.options.html,b),this.options.title=a,this.popperInstance.update()}},{key:'_clearTitleContent',value:function(a,b,c){1===c.nodeType||11===c.nodeType?b&&a.removeChild(c):b?a.innerHTML='':a.textContent=''}}]),g}(),h=function(){var a=this;this.show=function(){return a._show(a.reference,a.options)},this.hide=function(){return a._hide()},this.dispose=function(){return a._dispose()},this.toggle=function(){return a._isOpen?a.hide():a.show()},this.updateTitleContent=function(b){return a._updateTitleContent(b)},this._events=[],this._setTooltipNodeEvent=function(b,c,d,e){var f=b.relatedreference||b.toElement||b.relatedTarget;return!!a._tooltipNode.contains(f)&&(a._tooltipNode.addEventListener(b.type,function d(f){var g=f.relatedreference||f.toElement||f.relatedTarget;a._tooltipNode.removeEventListener(b.type,d),c.contains(g)||a._scheduleHide(c,e.delay,e,f)}),!0)}};return g});
13391//# sourceMappingURL=tooltip.min.js.map
13392
13393/*!
13394 * perfect-scrollbar v1.4.0
13395 * (c) 2018 Hyunje Jun
13396 * @license MIT
13397 */
13398(function (global, factory) {
13399	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
13400	typeof define === 'function' && define.amd ? define(factory) :
13401	(global.PerfectScrollbar = factory());
13402}(this, (function () { 'use strict';
13403
13404function get(element) {
13405  return getComputedStyle(element);
13406}
13407
13408function set(element, obj) {
13409  for (var key in obj) {
13410    var val = obj[key];
13411    if (typeof val === 'number') {
13412      val = val + "px";
13413    }
13414    element.style[key] = val;
13415  }
13416  return element;
13417}
13418
13419function div(className) {
13420  var div = document.createElement('div');
13421  div.className = className;
13422  return div;
13423}
13424
13425var elMatches =
13426  typeof Element !== 'undefined' &&
13427  (Element.prototype.matches ||
13428    Element.prototype.webkitMatchesSelector ||
13429    Element.prototype.mozMatchesSelector ||
13430    Element.prototype.msMatchesSelector);
13431
13432function matches(element, query) {
13433  if (!elMatches) {
13434    throw new Error('No element matching method supported');
13435  }
13436
13437  return elMatches.call(element, query);
13438}
13439
13440function remove(element) {
13441  if (element.remove) {
13442    element.remove();
13443  } else {
13444    if (element.parentNode) {
13445      element.parentNode.removeChild(element);
13446    }
13447  }
13448}
13449
13450function queryChildren(element, selector) {
13451  return Array.prototype.filter.call(element.children, function (child) { return matches(child, selector); }
13452  );
13453}
13454
13455var cls = {
13456  main: 'ps',
13457  element: {
13458    thumb: function (x) { return ("ps__thumb-" + x); },
13459    rail: function (x) { return ("ps__rail-" + x); },
13460    consuming: 'ps__child--consume',
13461  },
13462  state: {
13463    focus: 'ps--focus',
13464    clicking: 'ps--clicking',
13465    active: function (x) { return ("ps--active-" + x); },
13466    scrolling: function (x) { return ("ps--scrolling-" + x); },
13467  },
13468};
13469
13470/*
13471 * Helper methods
13472 */
13473var scrollingClassTimeout = { x: null, y: null };
13474
13475function addScrollingClass(i, x) {
13476  var classList = i.element.classList;
13477  var className = cls.state.scrolling(x);
13478
13479  if (classList.contains(className)) {
13480    clearTimeout(scrollingClassTimeout[x]);
13481  } else {
13482    classList.add(className);
13483  }
13484}
13485
13486function removeScrollingClass(i, x) {
13487  scrollingClassTimeout[x] = setTimeout(
13488    function () { return i.isAlive && i.element.classList.remove(cls.state.scrolling(x)); },
13489    i.settings.scrollingThreshold
13490  );
13491}
13492
13493function setScrollingClassInstantly(i, x) {
13494  addScrollingClass(i, x);
13495  removeScrollingClass(i, x);
13496}
13497
13498var EventElement = function EventElement(element) {
13499  this.element = element;
13500  this.handlers = {};
13501};
13502
13503var prototypeAccessors = { isEmpty: { configurable: true } };
13504
13505EventElement.prototype.bind = function bind (eventName, handler) {
13506  if (typeof this.handlers[eventName] === 'undefined') {
13507    this.handlers[eventName] = [];
13508  }
13509  this.handlers[eventName].push(handler);
13510  this.element.addEventListener(eventName, handler, false);
13511};
13512
13513EventElement.prototype.unbind = function unbind (eventName, target) {
13514    var this$1 = this;
13515
13516  this.handlers[eventName] = this.handlers[eventName].filter(function (handler) {
13517    if (target && handler !== target) {
13518      return true;
13519    }
13520    this$1.element.removeEventListener(eventName, handler, false);
13521    return false;
vendor: 5,047 bytes, lines 13522-13727
13522  });
13523};
13524
13525EventElement.prototype.unbindAll = function unbindAll () {
13526    var this$1 = this;
13527
13528  for (var name in this$1.handlers) {
13529    this$1.unbind(name);
13530  }
13531};
13532
13533prototypeAccessors.isEmpty.get = function () {
13534    var this$1 = this;
13535
13536  return Object.keys(this.handlers).every(
13537    function (key) { return this$1.handlers[key].length === 0; }
13538  );
13539};
13540
13541Object.defineProperties( EventElement.prototype, prototypeAccessors );
13542
13543var EventManager = function EventManager() {
13544  this.eventElements = [];
13545};
13546
13547EventManager.prototype.eventElement = function eventElement (element) {
13548  var ee = this.eventElements.filter(function (ee) { return ee.element === element; })[0];
13549  if (!ee) {
13550    ee = new EventElement(element);
13551    this.eventElements.push(ee);
13552  }
13553  return ee;
13554};
13555
13556EventManager.prototype.bind = function bind (element, eventName, handler) {
13557  this.eventElement(element).bind(eventName, handler);
13558};
13559
13560EventManager.prototype.unbind = function unbind (element, eventName, handler) {
13561  var ee = this.eventElement(element);
13562  ee.unbind(eventName, handler);
13563
13564  if (ee.isEmpty) {
13565    // remove
13566    this.eventElements.splice(this.eventElements.indexOf(ee), 1);
13567  }
13568};
13569
13570EventManager.prototype.unbindAll = function unbindAll () {
13571  this.eventElements.forEach(function (e) { return e.unbindAll(); });
13572  this.eventElements = [];
13573};
13574
13575EventManager.prototype.once = function once (element, eventName, handler) {
13576  var ee = this.eventElement(element);
13577  var onceHandler = function (evt) {
13578    ee.unbind(eventName, onceHandler);
13579    handler(evt);
13580  };
13581  ee.bind(eventName, onceHandler);
13582};
13583
13584function createEvent(name) {
13585  if (typeof window.CustomEvent === 'function') {
13586    return new CustomEvent(name);
13587  } else {
13588    var evt = document.createEvent('CustomEvent');
13589    evt.initCustomEvent(name, false, false, undefined);
13590    return evt;
13591  }
13592}
13593
13594var processScrollDiff = function(
13595  i,
13596  axis,
13597  diff,
13598  useScrollingClass,
13599  forceFireReachEvent
13600) {
13601  if ( useScrollingClass === void 0 ) useScrollingClass = true;
13602  if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false;
13603
13604  var fields;
13605  if (axis === 'top') {
13606    fields = [
13607      'contentHeight',
13608      'containerHeight',
13609      'scrollTop',
13610      'y',
13611      'up',
13612      'down' ];
13613  } else if (axis === 'left') {
13614    fields = [
13615      'contentWidth',
13616      'containerWidth',
13617      'scrollLeft',
13618      'x',
13619      'left',
13620      'right' ];
13621  } else {
13622    throw new Error('A proper axis should be provided');
13623  }
13624
13625  processScrollDiff$1(i, diff, fields, useScrollingClass, forceFireReachEvent);
13626};
13627
13628function processScrollDiff$1(
13629  i,
13630  diff,
13631  ref,
13632  useScrollingClass,
13633  forceFireReachEvent
13634) {
13635  var contentHeight = ref[0];
13636  var containerHeight = ref[1];
13637  var scrollTop = ref[2];
13638  var y = ref[3];
13639  var up = ref[4];
13640  var down = ref[5];
13641  if ( useScrollingClass === void 0 ) useScrollingClass = true;
13642  if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false;
13643
13644  var element = i.element;
13645
13646  // reset reach
13647  i.reach[y] = null;
13648
13649  // 1 for subpixel rounding
13650  if (element[scrollTop] < 1) {
13651    i.reach[y] = 'start';
13652  }
13653
13654  // 1 for subpixel rounding
13655  if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) {
13656    i.reach[y] = 'end';
13657  }
13658
13659  if (diff) {
13660    element.dispatchEvent(createEvent(("ps-scroll-" + y)));
13661
13662    if (diff < 0) {
13663      element.dispatchEvent(createEvent(("ps-scroll-" + up)));
13664    } else if (diff > 0) {
13665      element.dispatchEvent(createEvent(("ps-scroll-" + down)));
13666    }
13667
13668    if (useScrollingClass) {
13669      setScrollingClassInstantly(i, y);
13670    }
13671  }
13672
13673  if (i.reach[y] && (diff || forceFireReachEvent)) {
13674    element.dispatchEvent(createEvent(("ps-" + y + "-reach-" + (i.reach[y]))));
13675  }
13676}
13677
13678function toInt(x) {
13679  return parseInt(x, 10) || 0;
13680}
13681
13682function isEditable(el) {
13683  return (
13684    matches(el, 'input,[contenteditable]') ||
13685    matches(el, 'select,[contenteditable]') ||
13686    matches(el, 'textarea,[contenteditable]') ||
13687    matches(el, 'button,[contenteditable]')
13688  );
13689}
13690
13691function outerWidth(element) {
13692  var styles = get(element);
13693  return (
13694    toInt(styles.width) +
13695    toInt(styles.paddingLeft) +
13696    toInt(styles.paddingRight) +
13697    toInt(styles.borderLeftWidth) +
13698    toInt(styles.borderRightWidth)
13699  );
13700}
13701
13702var env = {
13703  isWebKit:
13704    typeof document !== 'undefined' &&
13705    'WebkitAppearance' in document.documentElement.style,
13706  supportsTouch:
13707    typeof window !== 'undefined' &&
13708    ('ontouchstart' in window ||
13709      (window.DocumentTouch && document instanceof window.DocumentTouch)),
13710  supportsIePointer:
13711    typeof navigator !== 'undefined' && navigator.msMaxTouchPoints,
13712  isChrome:
13713    typeof navigator !== 'undefined' &&
13714    /Chrome/i.test(navigator && navigator.userAgent),
13715};
13716
13717var updateGeometry = function(i) {
13718  var element = i.element;
13719  var roundedScrollTop = Math.floor(element.scrollTop);
13720
13721  i.containerWidth = element.clientWidth;
13722  i.containerHeight = element.clientHeight;
13723  i.contentWidth = element.scrollWidth;
13724  i.contentHeight = element.scrollHeight;
13725
13726  if (!element.contains(i.scrollbarXRail)) {
13727    // clean up and append
vendor: 4,424 bytes, lines 13728-13879
13728    queryChildren(element, cls.element.rail('x')).forEach(function (el) { return remove(el); }
13729    );
13730    element.appendChild(i.scrollbarXRail);
13731  }
13732  if (!element.contains(i.scrollbarYRail)) {
13733    // clean up and append
13734    queryChildren(element, cls.element.rail('y')).forEach(function (el) { return remove(el); }
13735    );
13736    element.appendChild(i.scrollbarYRail);
13737  }
13738
13739  if (
13740    !i.settings.suppressScrollX &&
13741    i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth
13742  ) {
13743    i.scrollbarXActive = true;
13744    i.railXWidth = i.containerWidth - i.railXMarginWidth;
13745    i.railXRatio = i.containerWidth / i.railXWidth;
13746    i.scrollbarXWidth = getThumbSize(
13747      i,
13748      toInt(i.railXWidth * i.containerWidth / i.contentWidth)
13749    );
13750    i.scrollbarXLeft = toInt(
13751      (i.negativeScrollAdjustment + element.scrollLeft) *
13752        (i.railXWidth - i.scrollbarXWidth) /
13753        (i.contentWidth - i.containerWidth)
13754    );
13755  } else {
13756    i.scrollbarXActive = false;
13757  }
13758
13759  if (
13760    !i.settings.suppressScrollY &&
13761    i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight
13762  ) {
13763    i.scrollbarYActive = true;
13764    i.railYHeight = i.containerHeight - i.railYMarginHeight;
13765    i.railYRatio = i.containerHeight / i.railYHeight;
13766    i.scrollbarYHeight = getThumbSize(
13767      i,
13768      toInt(i.railYHeight * i.containerHeight / i.contentHeight)
13769    );
13770    i.scrollbarYTop = toInt(
13771      roundedScrollTop *
13772        (i.railYHeight - i.scrollbarYHeight) /
13773        (i.contentHeight - i.containerHeight)
13774    );
13775  } else {
13776    i.scrollbarYActive = false;
13777  }
13778
13779  if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
13780    i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
13781  }
13782  if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
13783    i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
13784  }
13785
13786  updateCss(element, i);
13787
13788  if (i.scrollbarXActive) {
13789    element.classList.add(cls.state.active('x'));
13790  } else {
13791    element.classList.remove(cls.state.active('x'));
13792    i.scrollbarXWidth = 0;
13793    i.scrollbarXLeft = 0;
13794    element.scrollLeft = 0;
13795  }
13796  if (i.scrollbarYActive) {
13797    element.classList.add(cls.state.active('y'));
13798  } else {
13799    element.classList.remove(cls.state.active('y'));
13800    i.scrollbarYHeight = 0;
13801    i.scrollbarYTop = 0;
13802    element.scrollTop = 0;
13803  }
13804};
13805
13806function getThumbSize(i, thumbSize) {
13807  if (i.settings.minScrollbarLength) {
13808    thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
13809  }
13810  if (i.settings.maxScrollbarLength) {
13811    thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
13812  }
13813  return thumbSize;
13814}
13815
13816function updateCss(element, i) {
13817  var xRailOffset = { width: i.railXWidth };
13818  var roundedScrollTop = Math.floor(element.scrollTop);
13819
13820  if (i.isRtl) {
13821    xRailOffset.left =
13822      i.negativeScrollAdjustment +
13823      element.scrollLeft +
13824      i.containerWidth -
13825      i.contentWidth;
13826  } else {
13827    xRailOffset.left = element.scrollLeft;
13828  }
13829  if (i.isScrollbarXUsingBottom) {
13830    xRailOffset.bottom = i.scrollbarXBottom - roundedScrollTop;
13831  } else {
13832    xRailOffset.top = i.scrollbarXTop + roundedScrollTop;
13833  }
13834  set(i.scrollbarXRail, xRailOffset);
13835
13836  var yRailOffset = { top: roundedScrollTop, height: i.railYHeight };
13837  if (i.isScrollbarYUsingRight) {
13838    if (i.isRtl) {
13839      yRailOffset.right =
13840        i.contentWidth -
13841        (i.negativeScrollAdjustment + element.scrollLeft) -
13842        i.scrollbarYRight -
13843        i.scrollbarYOuterWidth;
13844    } else {
13845      yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
13846    }
13847  } else {
13848    if (i.isRtl) {
13849      yRailOffset.left =
13850        i.negativeScrollAdjustment +
13851        element.scrollLeft +
13852        i.containerWidth * 2 -
13853        i.contentWidth -
13854        i.scrollbarYLeft -
13855        i.scrollbarYOuterWidth;
13856    } else {
13857      yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
13858    }
13859  }
13860  set(i.scrollbarYRail, yRailOffset);
13861
13862  set(i.scrollbarX, {
13863    left: i.scrollbarXLeft,
13864    width: i.scrollbarXWidth - i.railBorderXWidth,
13865  });
13866  set(i.scrollbarY, {
13867    top: i.scrollbarYTop,
13868    height: i.scrollbarYHeight - i.railBorderYWidth,
13869  });
13870}
13871
13872var clickRail = function(i) {
13873  i.event.bind(i.scrollbarY, 'mousedown', function (e) { return e.stopPropagation(); });
13874  i.event.bind(i.scrollbarYRail, 'mousedown', function (e) {
13875    var positionTop =
13876      e.pageY -
13877      window.pageYOffset -
13878      i.scrollbarYRail.getBoundingClientRect().top;
13879    var direction = positionTop >
vendor: 6,750 bytes, lines 13879-14150
13879 i.scrollbarYTop ? 1 : -1;
13880
13881    i.element.scrollTop += direction * i.containerHeight;
13882    updateGeometry(i);
13883
13884    e.stopPropagation();
13885  });
13886
13887  i.event.bind(i.scrollbarX, 'mousedown', function (e) { return e.stopPropagation(); });
13888  i.event.bind(i.scrollbarXRail, 'mousedown', function (e) {
13889    var positionLeft =
13890      e.pageX -
13891      window.pageXOffset -
13892      i.scrollbarXRail.getBoundingClientRect().left;
13893    var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
13894
13895    i.element.scrollLeft += direction * i.containerWidth;
13896    updateGeometry(i);
13897
13898    e.stopPropagation();
13899  });
13900};
13901
13902var dragThumb = function(i) {
13903  bindMouseScrollHandler(i, [
13904    'containerWidth',
13905    'contentWidth',
13906    'pageX',
13907    'railXWidth',
13908    'scrollbarX',
13909    'scrollbarXWidth',
13910    'scrollLeft',
13911    'x',
13912    'scrollbarXRail' ]);
13913  bindMouseScrollHandler(i, [
13914    'containerHeight',
13915    'contentHeight',
13916    'pageY',
13917    'railYHeight',
13918    'scrollbarY',
13919    'scrollbarYHeight',
13920    'scrollTop',
13921    'y',
13922    'scrollbarYRail' ]);
13923};
13924
13925function bindMouseScrollHandler(
13926  i,
13927  ref
13928) {
13929  var containerHeight = ref[0];
13930  var contentHeight = ref[1];
13931  var pageY = ref[2];
13932  var railYHeight = ref[3];
13933  var scrollbarY = ref[4];
13934  var scrollbarYHeight = ref[5];
13935  var scrollTop = ref[6];
13936  var y = ref[7];
13937  var scrollbarYRail = ref[8];
13938
13939  var element = i.element;
13940
13941  var startingScrollTop = null;
13942  var startingMousePageY = null;
13943  var scrollBy = null;
13944
13945  function mouseMoveHandler(e) {
13946    element[scrollTop] =
13947      startingScrollTop + scrollBy * (e[pageY] - startingMousePageY);
13948    addScrollingClass(i, y);
13949    updateGeometry(i);
13950
13951    e.stopPropagation();
13952    e.preventDefault();
13953  }
13954
13955  function mouseUpHandler() {
13956    removeScrollingClass(i, y);
13957    i[scrollbarYRail].classList.remove(cls.state.clicking);
13958    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
13959  }
13960
13961  i.event.bind(i[scrollbarY], 'mousedown', function (e) {
13962    startingScrollTop = element[scrollTop];
13963    startingMousePageY = e[pageY];
13964    scrollBy =
13965      (i[contentHeight] - i[containerHeight]) /
13966      (i[railYHeight] - i[scrollbarYHeight]);
13967
13968    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
13969    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
13970
13971    i[scrollbarYRail].classList.add(cls.state.clicking);
13972
13973    e.stopPropagation();
13974    e.preventDefault();
13975  });
13976}
13977
13978var keyboard = function(i) {
13979  var element = i.element;
13980
13981  var elementHovered = function () { return matches(element, ':hover'); };
13982  var scrollbarFocused = function () { return matches(i.scrollbarX, ':focus') || matches(i.scrollbarY, ':focus'); };
13983
13984  function shouldPreventDefault(deltaX, deltaY) {
13985    var scrollTop = Math.floor(element.scrollTop);
13986    if (deltaX === 0) {
13987      if (!i.scrollbarYActive) {
13988        return false;
13989      }
13990      if (
13991        (scrollTop === 0 && deltaY > 0) ||
13992        (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)
13993      ) {
13994        return !i.settings.wheelPropagation;
13995      }
13996    }
13997
13998    var scrollLeft = element.scrollLeft;
13999    if (deltaY === 0) {
14000      if (!i.scrollbarXActive) {
14001        return false;
14002      }
14003      if (
14004        (scrollLeft === 0 && deltaX < 0) ||
14005        (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)
14006      ) {
14007        return !i.settings.wheelPropagation;
14008      }
14009    }
14010    return true;
14011  }
14012
14013  i.event.bind(i.ownerDocument, 'keydown', function (e) {
14014    if (
14015      (e.isDefaultPrevented && e.isDefaultPrevented()) ||
14016      e.defaultPrevented
14017    ) {
14018      return;
14019    }
14020
14021    if (!elementHovered() && !scrollbarFocused()) {
14022      return;
14023    }
14024
14025    var activeElement = document.activeElement
14026      ? document.activeElement
14027      : i.ownerDocument.activeElement;
14028    if (activeElement) {
14029      if (activeElement.tagName === 'IFRAME') {
14030        activeElement = activeElement.contentDocument.activeElement;
14031      } else {
14032        // go deeper if element is a webcomponent
14033        while (activeElement.shadowRoot) {
14034          activeElement = activeElement.shadowRoot.activeElement;
14035        }
14036      }
14037      if (isEditable(activeElement)) {
14038        return;
14039      }
14040    }
14041
14042    var deltaX = 0;
14043    var deltaY = 0;
14044
14045    switch (e.which) {
14046      case 37: // left
14047        if (e.metaKey) {
14048          deltaX = -i.contentWidth;
14049        } else if (e.altKey) {
14050          deltaX = -i.containerWidth;
14051        } else {
14052          deltaX = -30;
14053        }
14054        break;
14055      case 38: // up
14056        if (e.metaKey) {
14057          deltaY = i.contentHeight;
14058        } else if (e.altKey) {
14059          deltaY = i.containerHeight;
14060        } else {
14061          deltaY = 30;
14062        }
14063        break;
14064      case 39: // right
14065        if (e.metaKey) {
14066          deltaX = i.contentWidth;
14067        } else if (e.altKey) {
14068          deltaX = i.containerWidth;
14069        } else {
14070          deltaX = 30;
14071        }
14072        break;
14073      case 40: // down
14074        if (e.metaKey) {
14075          deltaY = -i.contentHeight;
14076        } else if (e.altKey) {
14077          deltaY = -i.containerHeight;
14078        } else {
14079          deltaY = -30;
14080        }
14081        break;
14082      case 32: // space bar
14083        if (e.shiftKey) {
14084          deltaY = i.containerHeight;
14085        } else {
14086          deltaY = -i.containerHeight;
14087        }
14088        break;
14089      case 33: // page up
14090        deltaY = i.containerHeight;
14091        break;
14092      case 34: // page down
14093        deltaY = -i.containerHeight;
14094        break;
14095      case 36: // home
14096        deltaY = i.contentHeight;
14097        break;
14098      case 35: // end
14099        deltaY = -i.contentHeight;
14100        break;
14101      default:
14102        return;
14103    }
14104
14105    if (i.settings.suppressScrollX && deltaX !== 0) {
14106      return;
14107    }
14108    if (i.settings.suppressScrollY && deltaY !== 0) {
14109      return;
14110    }
14111
14112    element.scrollTop -= deltaY;
14113    element.scrollLeft += deltaX;
14114    updateGeometry(i);
14115
14116    if (shouldPreventDefault(deltaX, deltaY)) {
14117      e.preventDefault();
14118    }
14119  });
14120};
14121
14122var wheel = function(i) {
14123  var element = i.element;
14124
14125  function shouldPreventDefault(deltaX, deltaY) {
14126    var roundedScrollTop = Math.floor(element.scrollTop);
14127    var isTop = element.scrollTop === 0;
14128    var isBottom =
14129      roundedScrollTop + element.offsetHeight === element.scrollHeight;
14130    var isLeft = element.scrollLeft === 0;
14131    var isRight =
14132      element.scrollLeft + element.offsetWidth === element.scrollWidth;
14133
14134    var hitsBound;
14135
14136    // pick axis with primary direction
14137    if (Math.abs(deltaY) > Math.abs(deltaX)) {
14138      hitsBound = isTop || isBottom;
14139    } else {
14140      hitsBound = isLeft || isRight;
14141    }
14142
14143    return hitsBound ? !i.settings.wheelPropagation : true;
14144  }
14145
14146  function getDeltaFromEvent(e) {
14147    var deltaX = e.deltaX;
14148    var deltaY = -1 * e.deltaY;
14149
14150    if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {
vendor: 10,958 bytes, lines 14151-14558
14151      // OS X Safari
14152      deltaX = -1 * e.wheelDeltaX / 6;
14153      deltaY = e.wheelDeltaY / 6;
14154    }
14155
14156    if (e.deltaMode && e.deltaMode === 1) {
14157      // Firefox in deltaMode 1: Line scrolling
14158      deltaX *= 10;
14159      deltaY *= 10;
14160    }
14161
14162    if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {
14163      // IE in some mouse drivers
14164      deltaX = 0;
14165      deltaY = e.wheelDelta;
14166    }
14167
14168    if (e.shiftKey) {
14169      // reverse axis with shift key
14170      return [-deltaY, -deltaX];
14171    }
14172    return [deltaX, deltaY];
14173  }
14174
14175  function shouldBeConsumedByChild(target, deltaX, deltaY) {
14176    // FIXME: this is a workaround for <select> issue in FF and IE #571
14177    if (!env.isWebKit && element.querySelector('select:focus')) {
14178      return true;
14179    }
14180
14181    if (!element.contains(target)) {
14182      return false;
14183    }
14184
14185    var cursor = target;
14186
14187    while (cursor && cursor !== element) {
14188      if (cursor.classList.contains(cls.element.consuming)) {
14189        return true;
14190      }
14191
14192      var style = get(cursor);
14193      var overflow = [style.overflow, style.overflowX, style.overflowY].join(
14194        ''
14195      );
14196
14197      // if scrollable
14198      if (overflow.match(/(scroll|auto)/)) {
14199        var maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
14200        if (maxScrollTop > 0) {
14201          if (
14202            !(cursor.scrollTop === 0 && deltaY > 0) &&
14203            !(cursor.scrollTop === maxScrollTop && deltaY < 0)
14204          ) {
14205            return true;
14206          }
14207        }
14208        var maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;
14209        if (maxScrollLeft > 0) {
14210          if (
14211            !(cursor.scrollLeft === 0 && deltaX < 0) &&
14212            !(cursor.scrollLeft === maxScrollLeft && deltaX > 0)
14213          ) {
14214            return true;
14215          }
14216        }
14217      }
14218
14219      cursor = cursor.parentNode;
14220    }
14221
14222    return false;
14223  }
14224
14225  function mousewheelHandler(e) {
14226    var ref = getDeltaFromEvent(e);
14227    var deltaX = ref[0];
14228    var deltaY = ref[1];
14229
14230    if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
14231      return;
14232    }
14233
14234    var shouldPrevent = false;
14235    if (!i.settings.useBothWheelAxes) {
14236      // deltaX will only be used for horizontal scrolling and deltaY will
14237      // only be used for vertical scrolling - this is the default
14238      element.scrollTop -= deltaY * i.settings.wheelSpeed;
14239      element.scrollLeft += deltaX * i.settings.wheelSpeed;
14240    } else if (i.scrollbarYActive && !i.scrollbarXActive) {
14241      // only vertical scrollbar is active and useBothWheelAxes option is
14242      // active, so let's scroll vertical bar using both mouse wheel axes
14243      if (deltaY) {
14244        element.scrollTop -= deltaY * i.settings.wheelSpeed;
14245      } else {
14246        element.scrollTop += deltaX * i.settings.wheelSpeed;
14247      }
14248      shouldPrevent = true;
14249    } else if (i.scrollbarXActive && !i.scrollbarYActive) {
14250      // useBothWheelAxes and only horizontal bar is active, so use both
14251      // wheel axes for horizontal bar
14252      if (deltaX) {
14253        element.scrollLeft += deltaX * i.settings.wheelSpeed;
14254      } else {
14255        element.scrollLeft -= deltaY * i.settings.wheelSpeed;
14256      }
14257      shouldPrevent = true;
14258    }
14259
14260    updateGeometry(i);
14261
14262    shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);
14263    if (shouldPrevent && !e.ctrlKey) {
14264      e.stopPropagation();
14265      e.preventDefault();
14266    }
14267  }
14268
14269  if (typeof window.onwheel !== 'undefined') {
14270    i.event.bind(element, 'wheel', mousewheelHandler);
14271  } else if (typeof window.onmousewheel !== 'undefined') {
14272    i.event.bind(element, 'mousewheel', mousewheelHandler);
14273  }
14274};
14275
14276var touch = function(i) {
14277  if (!env.supportsTouch && !env.supportsIePointer) {
14278    return;
14279  }
14280
14281  var element = i.element;
14282
14283  function shouldPrevent(deltaX, deltaY) {
14284    var scrollTop = Math.floor(element.scrollTop);
14285    var scrollLeft = element.scrollLeft;
14286    var magnitudeX = Math.abs(deltaX);
14287    var magnitudeY = Math.abs(deltaY);
14288
14289    if (magnitudeY > magnitudeX) {
14290      // user is perhaps trying to swipe up/down the page
14291
14292      if (
14293        (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||
14294        (deltaY > 0 && scrollTop === 0)
14295      ) {
14296        // set prevent for mobile Chrome refresh
14297        return window.scrollY === 0 && deltaY > 0 && env.isChrome;
14298      }
14299    } else if (magnitudeX > magnitudeY) {
14300      // user is perhaps trying to swipe left/right across the page
14301
14302      if (
14303        (deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) ||
14304        (deltaX > 0 && scrollLeft === 0)
14305      ) {
14306        return true;
14307      }
14308    }
14309
14310    return true;
14311  }
14312
14313  function applyTouchMove(differenceX, differenceY) {
14314    element.scrollTop -= differenceY;
14315    element.scrollLeft -= differenceX;
14316
14317    updateGeometry(i);
14318  }
14319
14320  var startOffset = {};
14321  var startTime = 0;
14322  var speed = {};
14323  var easingLoop = null;
14324
14325  function getTouch(e) {
14326    if (e.targetTouches) {
14327      return e.targetTouches[0];
14328    } else {
14329      // Maybe IE pointer
14330      return e;
14331    }
14332  }
14333
14334  function shouldHandle(e) {
14335    if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) {
14336      return false;
14337    }
14338    if (e.targetTouches && e.targetTouches.length === 1) {
14339      return true;
14340    }
14341    if (
14342      e.pointerType &&
14343      e.pointerType !== 'mouse' &&
14344      e.pointerType !== e.MSPOINTER_TYPE_MOUSE
14345    ) {
14346      return true;
14347    }
14348    return false;
14349  }
14350
14351  function touchStart(e) {
14352    if (!shouldHandle(e)) {
14353      return;
14354    }
14355
14356    var touch = getTouch(e);
14357
14358    startOffset.pageX = touch.pageX;
14359    startOffset.pageY = touch.pageY;
14360
14361    startTime = new Date().getTime();
14362
14363    if (easingLoop !== null) {
14364      clearInterval(easingLoop);
14365    }
14366  }
14367
14368  function shouldBeConsumedByChild(target, deltaX, deltaY) {
14369    if (!element.contains(target)) {
14370      return false;
14371    }
14372
14373    var cursor = target;
14374
14375    while (cursor && cursor !== element) {
14376      if (cursor.classList.contains(cls.element.consuming)) {
14377        return true;
14378      }
14379
14380      var style = get(cursor);
14381      var overflow = [style.overflow, style.overflowX, style.overflowY].join(
14382        ''
14383      );
14384
14385      // if scrollable
14386      if (overflow.match(/(scroll|auto)/)) {
14387        var maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
14388        if (maxScrollTop > 0) {
14389          if (
14390            !(cursor.scrollTop === 0 && deltaY > 0) &&
14391            !(cursor.scrollTop === maxScrollTop && deltaY < 0)
14392          ) {
14393            return true;
14394          }
14395        }
14396        var maxScrollLeft = cursor.scrollLeft - cursor.clientWidth;
14397        if (maxScrollLeft > 0) {
14398          if (
14399            !(cursor.scrollLeft === 0 && deltaX < 0) &&
14400            !(cursor.scrollLeft === maxScrollLeft && deltaX > 0)
14401          ) {
14402            return true;
14403          }
14404        }
14405      }
14406
14407      cursor = cursor.parentNode;
14408    }
14409
14410    return false;
14411  }
14412
14413  function touchMove(e) {
14414    if (shouldHandle(e)) {
14415      var touch = getTouch(e);
14416
14417      var currentOffset = { pageX: touch.pageX, pageY: touch.pageY };
14418
14419      var differenceX = currentOffset.pageX - startOffset.pageX;
14420      var differenceY = currentOffset.pageY - startOffset.pageY;
14421
14422      if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) {
14423        return;
14424      }
14425
14426      applyTouchMove(differenceX, differenceY);
14427      startOffset = currentOffset;
14428
14429      var currentTime = new Date().getTime();
14430
14431      var timeGap = currentTime - startTime;
14432      if (timeGap > 0) {
14433        speed.x = differenceX / timeGap;
14434        speed.y = differenceY / timeGap;
14435        startTime = currentTime;
14436      }
14437
14438      if (shouldPrevent(differenceX, differenceY)) {
14439        e.preventDefault();
14440      }
14441    }
14442  }
14443  function touchEnd() {
14444    if (i.settings.swipeEasing) {
14445      clearInterval(easingLoop);
14446      easingLoop = setInterval(function() {
14447        if (i.isInitialized) {
14448          clearInterval(easingLoop);
14449          return;
14450        }
14451
14452        if (!speed.x && !speed.y) {
14453          clearInterval(easingLoop);
14454          return;
14455        }
14456
14457        if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
14458          clearInterval(easingLoop);
14459          return;
14460        }
14461
14462        applyTouchMove(speed.x * 30, speed.y * 30);
14463
14464        speed.x *= 0.8;
14465        speed.y *= 0.8;
14466      }, 10);
14467    }
14468  }
14469
14470  if (env.supportsTouch) {
14471    i.event.bind(element, 'touchstart', touchStart);
14472    i.event.bind(element, 'touchmove', touchMove);
14473    i.event.bind(element, 'touchend', touchEnd);
14474  } else if (env.supportsIePointer) {
14475    if (window.PointerEvent) {
14476      i.event.bind(element, 'pointerdown', touchStart);
14477      i.event.bind(element, 'pointermove', touchMove);
14478      i.event.bind(element, 'pointerup', touchEnd);
14479    } else if (window.MSPointerEvent) {
14480      i.event.bind(element, 'MSPointerDown', touchStart);
14481      i.event.bind(element, 'MSPointerMove', touchMove);
14482      i.event.bind(element, 'MSPointerUp', touchEnd);
14483    }
14484  }
14485};
14486
14487var defaultSettings = function () { return ({
14488  handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'],
14489  maxScrollbarLength: null,
14490  minScrollbarLength: null,
14491  scrollingThreshold: 1000,
14492  scrollXMarginOffset: 0,
14493  scrollYMarginOffset: 0,
14494  suppressScrollX: false,
14495  suppressScrollY: false,
14496  swipeEasing: true,
14497  useBothWheelAxes: false,
14498  wheelPropagation: true,
14499  wheelSpeed: 1,
14500}); };
14501
14502var handlers = {
14503  'click-rail': clickRail,
14504  'drag-thumb': dragThumb,
14505  keyboard: keyboard,
14506  wheel: wheel,
14507  touch: touch,
14508};
14509
14510var PerfectScrollbar = function PerfectScrollbar(element, userSettings) {
14511  var this$1 = this;
14512  if ( userSettings === void 0 ) userSettings = {};
14513
14514  if (typeof element === 'string') {
14515    element = document.querySelector(element);
14516  }
14517
14518  if (!element || !element.nodeName) {
14519    throw new Error('no element is specified to initialize PerfectScrollbar');
14520  }
14521
14522  this.element = element;
14523
14524  element.classList.add(cls.main);
14525
14526  this.settings = defaultSettings();
14527  for (var key in userSettings) {
14528    this$1.settings[key] = userSettings[key];
14529  }
14530
14531  this.containerWidth = null;
14532  this.containerHeight = null;
14533  this.contentWidth = null;
14534  this.contentHeight = null;
14535
14536  var focus = function () { return element.classList.add(cls.state.focus); };
14537  var blur = function () { return element.classList.remove(cls.state.focus); };
14538
14539  this.isRtl = get(element).direction === 'rtl';
14540  this.isNegativeScroll = (function () {
14541    var originalScrollLeft = element.scrollLeft;
14542    var result = null;
14543    element.scrollLeft = -1;
14544    result = element.scrollLeft < 0;
14545    element.scrollLeft = originalScrollLeft;
14546    return result;
14547  })();
14548  this.negativeScrollAdjustment = this.isNegativeScroll
14549    ? element.scrollWidth - element.clientWidth
14550    : 0;
14551  this.event = new EventManager();
14552  this.ownerDocument = element.ownerDocument || document;
14553
14554  this.scrollbarXRail = div(cls.element.rail('x'));
14555  element.appendChild(this.scrollbarXRail);
14556  this.scrollbarX = div(cls.element.thumb('x'));
14557  this.scrollbarXRail.appendChild(this.scrollbarX);
14558  this.scrollbarX.setAttribute('tabindex', 0);
vendor: 4,650 bytes, lines 14559-14704
14559  this.event.bind(this.scrollbarX, 'focus', focus);
14560  this.event.bind(this.scrollbarX, 'blur', blur);
14561  this.scrollbarXActive = null;
14562  this.scrollbarXWidth = null;
14563  this.scrollbarXLeft = null;
14564  var railXStyle = get(this.scrollbarXRail);
14565  this.scrollbarXBottom = parseInt(railXStyle.bottom, 10);
14566  if (isNaN(this.scrollbarXBottom)) {
14567    this.isScrollbarXUsingBottom = false;
14568    this.scrollbarXTop = toInt(railXStyle.top);
14569  } else {
14570    this.isScrollbarXUsingBottom = true;
14571  }
14572  this.railBorderXWidth =
14573    toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth);
14574  // Set rail to display:block to calculate margins
14575  set(this.scrollbarXRail, { display: 'block' });
14576  this.railXMarginWidth =
14577    toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight);
14578  set(this.scrollbarXRail, { display: '' });
14579  this.railXWidth = null;
14580  this.railXRatio = null;
14581
14582  this.scrollbarYRail = div(cls.element.rail('y'));
14583  element.appendChild(this.scrollbarYRail);
14584  this.scrollbarY = div(cls.element.thumb('y'));
14585  this.scrollbarYRail.appendChild(this.scrollbarY);
14586  this.scrollbarY.setAttribute('tabindex', 0);
14587  this.event.bind(this.scrollbarY, 'focus', focus);
14588  this.event.bind(this.scrollbarY, 'blur', blur);
14589  this.scrollbarYActive = null;
14590  this.scrollbarYHeight = null;
14591  this.scrollbarYTop = null;
14592  var railYStyle = get(this.scrollbarYRail);
14593  this.scrollbarYRight = parseInt(railYStyle.right, 10);
14594  if (isNaN(this.scrollbarYRight)) {
14595    this.isScrollbarYUsingRight = false;
14596    this.scrollbarYLeft = toInt(railYStyle.left);
14597  } else {
14598    this.isScrollbarYUsingRight = true;
14599  }
14600  this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null;
14601  this.railBorderYWidth =
14602    toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth);
14603  set(this.scrollbarYRail, { display: 'block' });
14604  this.railYMarginHeight =
14605    toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom);
14606  set(this.scrollbarYRail, { display: '' });
14607  this.railYHeight = null;
14608  this.railYRatio = null;
14609
14610  this.reach = {
14611    x:
14612      element.scrollLeft <= 0
14613        ? 'start'
14614        : element.scrollLeft >= this.contentWidth - this.containerWidth
14615          ? 'end'
14616          : null,
14617    y:
14618      element.scrollTop <= 0
14619        ? 'start'
14620        : element.scrollTop >= this.contentHeight - this.containerHeight
14621          ? 'end'
14622          : null,
14623  };
14624
14625  this.isAlive = true;
14626
14627  this.settings.handlers.forEach(function (handlerName) { return handlers[handlerName](this$1); });
14628
14629  this.lastScrollTop = Math.floor(element.scrollTop); // for onScroll only
14630  this.lastScrollLeft = element.scrollLeft; // for onScroll only
14631  this.event.bind(this.element, 'scroll', function (e) { return this$1.onScroll(e); });
14632  updateGeometry(this);
14633};
14634
14635PerfectScrollbar.prototype.update = function update () {
14636  if (!this.isAlive) {
14637    return;
14638  }
14639
14640  // Recalcuate negative scrollLeft adjustment
14641  this.negativeScrollAdjustment = this.isNegativeScroll
14642    ? this.element.scrollWidth - this.element.clientWidth
14643    : 0;
14644
14645  // Recalculate rail margins
14646  set(this.scrollbarXRail, { display: 'block' });
14647  set(this.scrollbarYRail, { display: 'block' });
14648  this.railXMarginWidth =
14649    toInt(get(this.scrollbarXRail).marginLeft) +
14650    toInt(get(this.scrollbarXRail).marginRight);
14651  this.railYMarginHeight =
14652    toInt(get(this.scrollbarYRail).marginTop) +
14653    toInt(get(this.scrollbarYRail).marginBottom);
14654
14655  // Hide scrollbars not to affect scrollWidth and scrollHeight
14656  set(this.scrollbarXRail, { display: 'none' });
14657  set(this.scrollbarYRail, { display: 'none' });
14658
14659  updateGeometry(this);
14660
14661  processScrollDiff(this, 'top', 0, false, true);
14662  processScrollDiff(this, 'left', 0, false, true);
14663
14664  set(this.scrollbarXRail, { display: '' });
14665  set(this.scrollbarYRail, { display: '' });
14666};
14667
14668PerfectScrollbar.prototype.onScroll = function onScroll (e) {
14669  if (!this.isAlive) {
14670    return;
14671  }
14672
14673  updateGeometry(this);
14674  processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop);
14675  processScrollDiff(
14676    this,
14677    'left',
14678    this.element.scrollLeft - this.lastScrollLeft
14679  );
14680
14681  this.lastScrollTop = Math.floor(this.element.scrollTop);
14682  this.lastScrollLeft = this.element.scrollLeft;
14683};
14684
14685PerfectScrollbar.prototype.destroy = function destroy () {
14686  if (!this.isAlive) {
14687    return;
14688  }
14689
14690  this.event.unbindAll();
14691  remove(this.scrollbarX);
14692  remove(this.scrollbarY);
14693  remove(this.scrollbarXRail);
14694  remove(this.scrollbarYRail);
14695  this.removePsClasses();
14696
14697  // unset elements
14698  this.element = null;
14699  this.scrollbarX = null;
14700  this.scrollbarY = null;
14701  this.scrollbarXRail = null;
14702  this.scrollbarYRail = null;
14703
14704  this.isAlive = false;
14705};
14706
14707PerfectScrollbar.prototype.removePsClasses = function removePsClasses () {
14708  this.element.className = this.element.className
14709    .split(' ')
14710    .filter(function (name) { return !name.match(/^ps([-_].+|)$/); })
14711    .join(' ');
14712};
14713
14714return PerfectScrollbar;
14715
14716})));
14717
14718function _classCallCheck(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}var Sticky=function(){function t(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};_classCallCheck(this,t),this.selector=i,this.elements=[],this.version="1.2.0",this.vp=this.getViewportSize(),this.body=document.querySelector("body"),this.options={wrap:e.wrap||!1,marginTop:e.marginTop||0,stickyFor:e.stickyFor||0,stickyClass:e.stickyClass||null,stickyContainer:e.stickyContainer||"body"},this.updateScrollTopPosition=this.updateScrollTopPosition.bind(this),this.updateScrollTopPosition(),window.addEventListener("load",this.updateScrollTopPosition),window.addEventListener("scroll",this.updateScrollTopPosition),this.run()}return t.prototype.run=function(){var t=this,i=setInterval(function(){if("complete"===document.readyState){clearInterval(i);var e=document.querySelectorAll(t.selector);t.forEach(e,function(i){return t.renderElement(i)})}},10)},t.prototype.renderElement=function(t){var i=this;t.sticky={},t.sticky.active=!1,t.sticky.marginTop=parseInt(t.getAttribute("data-margin-top"))||this.options.marginTop,t.sticky.stickyFor=parseInt(t.getAttribute("data-sticky-for"))||this.options.stickyFor,t.sticky.stickyClass=t.getAttribute("data-sticky-class")||this.options.stickyClass,t.sticky.wrap=!!t.hasAttribute("data-sticky-wrap")||this.options.wrap,t.sticky.stickyContainer=this.options.stickyContainer,t.sticky.container=this.getStickyContainer(t),t.sticky.container.rect=this.getRectangle(t.sticky.container),t.sticky.rect=this.getRectangle(t),"img"===t.tagName.toLowerCase()&&(t.onload=function(){return t.sticky.rect=i.getRectangle(t)}),t.sticky.wrap&&this.wrapElement(t),this.activate(t)},t.prototype.wrapElement=function(t){t.insertAdjacentHTML("beforebegin","<span></span>"),t.previousSibling.appendChild(t)},t.prototype.activate=function(t){t.sticky.rect.top+t.sticky.rect.height<t.sticky.container.rect.top+t.sticky.container.rect.height&&t.sticky.stickyFor<this.vp.width&&!t.sticky.active&&(t.sticky.active=!0),this.elements.indexOf(t)<0&&this.elements.push(t),t.sticky.resizeEvent||(this.initResizeEvents(t),t.sticky.resizeEvent=!0),t.sticky.scrollEvent||(this.initScrollEvents(t),t.sticky.scrollEvent=!0),this.setPosition(t)},t.prototype.initResizeEvents=function(t){var i=this;t.sticky.resizeListener=function(){return i.onResizeEvents(t)},window.addEventListener("resize",t.sticky.resizeListener)},t.prototype.destroyResizeEvents=function(t){window.removeEventListener("resize",t.sticky.resizeListener)},t.prototype.onResizeEvents=function(t){this.vp=this.getViewportSize(),t.sticky.rect=this.getRectangle(t),t.sticky.container.rect=this.getRectangle(t.sticky.container),t.sticky.rect.top+t.sticky.rect.height<t.sticky.container.rect.top+t.sticky.container.rect.height&&t.sticky.stickyFor<this.vp.width&&!t.sticky.active?t.sticky.active=!0:(t.sticky.rect.top+t.sticky.rect.height>=t.sticky.container.rect.top+t.sticky.container.rect.height||t.sticky.stickyFor>=this.vp.width&&t.sticky.active)&&(t.sticky.active=!1),this.setPosition(t)},t.prototype.initScrollEvents=function(t){var i=this;t.sticky.scrollListener=function(){return i.onScrollEvents(t)},window.addEventListener("scroll",t.sticky.scrollListener)},t.prototype.destroyScrollEvents=function(t){window.removeEventListener("scroll",t.sticky.scrollListener)},t.prototype.onScrollEvents=function(t){t.sticky.active&&this.setPosition(t)},t.prototype.setPosition=function(t){this.css(t,{position:"",width:"",top:"",left:""}),this.vp.height<t.sticky.rect.height||!t.sticky.active||(t.sticky.rect.width||(t.sticky.rect=this.getRectangle(t)),t.sticky.wrap&&this.css(t.parentNode,{display:"block",width:t.sticky.rect.width+"px",height:t.sticky.rect.height+"px"}),0===t.sticky.rect.top&&t.sticky.container===this.body?this.css(t,{position:"fixed",top:t.sticky.rect.top+"px",left:t.sticky.rect.left+"px",width:t.sticky.rect.width+"px"}):this.scrollTop>t.sticky.rect.top-t.sticky.marginTop?(this.css(t,{position:"fixed",width:t.sticky.rect.width+"px",left:t.sticky.rect.left+"px"}),this.scrollTop+t.sticky.rect.height+t.sticky.marginTop>t.sticky.container.rect.top+t.sticky.container.offsetHeight?(t.sticky.stickyClass&&t.classList.remove(t.sticky.stickyClass),this.css(t,{top:t.sticky.container.rect.top+t.sticky.container.offsetHeight-(this.scrollTop+t.sticky.rect.height)+"px"})):(t.sticky.stickyClass&&t.classList.add(t.sticky.stickyClass),this.css(t,{top:t.sticky.marginTop+"px"}))):(t.sticky.stickyClass&&t.classList.remove(t.sticky.stickyClass),this.css(t,{position:"",width:"",top:"",left:""}),t.sticky.wrap&&this.css(t.parentNode,{display:"",width:"",height:""})))},t.prototype.update=function(){var t=this;this.forEach(this.elements,function(i){i.sticky.rect=t.getRectangle(i),i.sticky.container.rect=t.getRectangle(i.sticky.container),t.activate(i),t.setPosition(i)})},t.prototype.destroy=function(){var t=this;this.forEach(this.elements,function(i){t.destroyResizeEvents(i),t.destroyScrollEvents(i),delete i.sticky})},t.prototype.getStickyContainer=function(t){for(var i=t.parentNode;!i.hasAttribute("data-sticky-container")&&!i.parentNode.querySelector(t.sticky.stickyContainer)&&i!==this.body;)i=i.parentNode;return i},t.prototype.getRectangle=function(t){this.css(t,{position:"",width:"",top:"",left:""});var i=Math.max(t.offsetWidth,t.clientWidth,t.scrollWidth),e=Math.max(t.offsetHeight,t.clientHeight,t.scrollHeight),s=0,o=0;do s+=t.offsetTop||0,o+=t.offsetLeft||0,t=t.offsetParent;while(t);return{top:s,left:o,width:i,height:e}},t.prototype.getViewportSize=function(){return{width:Math.max(document.documentElement.clientWidth,window.innerWidth||0),height:Math.max(document.documentElement.clientHeight,window.innerHeight||0)}},t.prototype.updateScrollTopPosition=function(){this.scrollTop=(window.pageYOffset||document.scrollTop)-(document.clientTop||0)||0},t.prototype.forEach=function(t,i){for(var e=0,s=t.length;e<s;e++)i(t[e])},t.prototype.css=function(t,i){for(var e in i)i.hasOwnProperty(e)&&(t.style[e]=i[e])},t}();!function(t,i){"undefined"!=typeof exports?module.exports=i:"function"==typeof define&&define.amd?define([],i):t.Sticky=i}(this,Sticky);
14719(function (factory) {
14720
14721    if ( typeof define === 'function' && define.amd ) {
14722
14723        // AMD. Register as an anonymous module.
14724        define([], factory);
14725
14726    } else if ( typeof exports === 'object' ) {
14727
14728        // Node/CommonJS
14729        module.exports = factory();
14730
14731    } else {
14732
14733        // Browser globals
14734        window.wNumb = factory();
14735    }
14736
14737}(function(){
14738
14739	'use strict';
14740
14741var FormatOptions = [
14742	'decimals',
14743	'thousand',
14744	'mark',
14745	'prefix',
14746	'suffix',
14747	'encoder',
14748	'decoder',
14749	'negativeBefore',
14750	'negative',
14751	'edit',
14752	'undo'
14753];
14754
14755// General
14756
14757	// Reverse a string
14758	function strReverse ( a ) {
14759		return a.split('').reverse().join('');
14760	}
14761
14762	// Check if a string starts with a specified prefix.
14763	function strStartsWith ( input, match ) {
14764		return input.substring(0, match.length) === match;
14765	}
14766
14767	// Check is a string ends in a specified suffix.
14768	function strEndsWith ( input, match ) {
14769		return input.slice(-1 * match.length) === match;
14770	}
14771
14772	// Throw an error if formatting options are incompatible.
14773	function throwEqualError( F, a, b ) {
14774		if ( (F[a] || F[b]) && (F[a] === F[b]) ) {
14775			throw new Error(a);
14776		}
14777	}
14778
14779	// Check if a number is finite and not NaN
14780	function isValidNumber ( input ) {
14781		return typeof input === 'number' && isFinite( input );
14782	}
14783
14784	// Provide rounding-accurate toFixed method.
14785	// Borrowed: http://stackoverflow.com/a/21323330/775265
14786	function toFixed ( value, exp ) {
14787		value = value.toString().split('e');
14788		value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));
14789		value = value.toString().split('e');
14790		return (+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))).toFixed(exp);
14791	}
14792
14793
14794// Formatting
14795
14796	// Accept a number as input, output formatted string.
14797	function formatTo ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) {
14798
14799		var originalInput = input, inputIsNegative, inputPieces, inputBase, inputDecimals = '', output = '';
14800
14801		// Apply user encoder to the input.
14802		// Expected outcome: number.
14803		if ( encoder ) {
14804			input = encoder(input);
14805		}
14806
14807		// Stop if no valid number was provided, the number is infinite or NaN.
14808		if ( !isValidNumber(input) ) {
14809			return false;
14810		}
14811
14812		// Rounding away decimals might cause a value of -0
14813		// when using very small ranges. Remove those cases.
14814		if ( decimals !== false && parseFloat(input.toFixed(decimals)) === 0 ) {
14815			input = 0;
14816		}
14817
14818		// Formatting is done on absolute numbers,
14819		// decorated by an optional negative symbol.
14820		if ( input < 0 ) {
14821			inputIsNegative = true;
14822			input = Math.abs(input);
14823		}
14824
14825		// Reduce the number of decimals to the specified option.
14826		if ( decimals !== false ) {
14827			input = toFixed( input, decimals );
14828		}
14829
14830		// Transform the number into a string, so it can be split.
14831		input = input.toString();
14832
14833		// Break the number on the decimal separator.
14834		if ( input.indexOf('.') !== -1 ) {
14835			inputPieces = input.split('.');
14836
14837			inputBase = inputPieces[0];
14838
14839			if ( mark ) {
14840				inputDecimals = mark + inputPieces[1];
14841			}
14842
14843		} else {
14844
14845		// If it isn't split, the entire number will do.
14846			inputBase = input;
14847		}
14848
14849		// Group numbers in sets of three.
14850		if ( thousand ) {
14851			inputBase = strReverse(inputBase).match(/.{1,3}/g);
14852			inputBase = strReverse(inputBase.join( strReverse( thousand ) ));
14853		}
14854
14855		// If the number is negative, prefix with negation symbol.
14856		if ( inputIsNegative && negativeBefore ) {
14857			output += negativeBefore;
14858		}
14859
14860		// Prefix the number
14861		if ( prefix ) {
14862			output += prefix;
14863		}
14864
14865		// Normal negative option comes after the prefix. Defaults to '-'.
14866		if ( inputIsNegative && negative ) {
14867			output += negative;
14868		}
14869
14870		// Append the actual number.
14871		output += inputBase;
14872		output += inputDecimals;
14873
14874		// Apply the suffix.
14875		if ( suffix ) {
14876			output += suffix;
14877		}
14878
14879		// Run the output through a user-specified post-formatter.
14880		if ( edit ) {
14881			output = edit ( output, originalInput );
14882		}
14883
14884		// All done.
14885		return output;
14886	}
14887
14888	// Accept a sting as input, output decoded number.
14889	function formatFrom ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) {
14890
14891		var originalInput = input, inputIsNegative, output = '';
14892
14893		// User defined pre-decoder. Result must be a non empty string.
14894		if ( undo ) {
14895			input = undo(input);
14896		}
14897
14898		// Test the input. Can't be empty.
14899		if ( !input || typeof input !== 'string' ) {
14900			return false;
14901		}
14902
14903		// If the string starts with the negativeBefore value: remove it.
14904		// Remember is was there, the number is negative.
14905		if ( negativeBefore && strStartsWith(input, negativeBefore) ) {
14906			input = input.replace(negativeBefore, '');
14907			inputIsNegative = true;
14908		}
14909
14910		// Repeat the same procedure for the prefix.
14911		if ( prefix && strStartsWith(input, prefix) ) {
14912			input = input.replace(prefix, '');
14913		}
14914
14915		// And again for negative.
14916		if ( negative && strStartsWith(input, negative) ) {
14917			input = input.replace(negative, '');
14918			inputIsNegative = true;
14919		}
14920
14921		// Remove the suffix.
14922		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
14923		if ( suffix && strEndsWith(input, suffix) ) {
14924			input = input.slice(0, -1 * suffix.length);
14925		}
14926
14927		// Remove the thousand grouping.
14928		if ( thousand ) {
14929			input = input.split(thousand).join('');
14930		}
14931
14932		// Set the decimal separator back to period.
14933		if ( mark ) {
14934			input = input.replace(mark, '.');
14935		}
14936
14937		// Prepend the negative symbol.
14938		if ( inputIsNegative ) {
14939			output += '-';
14940		}
14941
14942		// Add the number
14943		output += input;
14944
14945		// Trim all non-numeric characters (allow '.' and '-');
14946		output = output.replace(/[^0-9\.\-.]/g, '');
14947
14948		// The value contains no parse-able number.
14949		if ( output === '' ) {
14950			return false;
14951		}
14952
14953		// Covert to number.
14954		output = Number(output);
14955
14956		// Run the user-specified post-decoder.
14957		if ( decoder ) {
14958			output = decoder(output);
14959		}
14960
14961		// Check is the output is valid, otherwise: return false.
14962		if ( !isValidNumber(output) ) {
14963			return false;
14964		}
14965
14966		return output;
14967	}
14968
14969
14970// Framework
14971
14972	// Validate formatting options
14973	function validate ( inputOptions ) {
14974
14975		var i, optionName, optionValue,
14976			filteredOptions = {};
14977
14978		if ( inputOptions['suffix'] === undefined ) {
14979			inputOptions['suffix'] = inputOptions['postfix'];
14980		}
14981
14982		for ( i = 0; i < FormatOptions.length; i+=1 ) {
14983
14984			optionName = FormatOptions[i];
14985			optionValue = inputOptions[optionName];
14986
14987			if ( optionValue === undefined ) {
14988
14989				// Only default if negativeBefore isn't set.
14990				if ( optionName === 'negative' && !filteredOptions.negativeBefore ) {
14991					filteredOptions[optionName] = '-';
14992				// Don't set a default for mark when 'thousand' is set.
14993				} else if ( optionName === 'mark' && filteredOptions.thousand !== '.' ) {
14994					filteredOptions[optionName] = '.';
14995				} else {
14996					filteredOptions[optionName] = false;
14997				}
14998
14999			// Floating points in JS are stable up to 7 decimals.
15000			} else if ( optionName === 'decimals' ) {
15001				if ( optionValue >= 0 && optionValue < 8 ) {
15002					filteredOptions[optionName] = optionValue;
15003				} else {
15004					throw new Error(optionName);
15005				}
15006
15007			// These options, when provided, must be functions.
15008			} else if ( optionName === 'encoder' || optionName === 'decoder' || optionName === 'edit' || optionName === 'undo' ) {
15009				if ( typeof optionValue === 'function' ) {
15010					filteredOptions[optionName] = optionValue;
15011				} else {
15012					throw new Error(optionName);
15013				}
15014
15015			// Other options are strings.
15016			} else {
15017
15018				if ( typeof optionValue === 'string' ) {
15019					filteredOptions[optionName] = optionValue;
15020				} else {
15021					throw new Error(optionName);
15022				}
15023			}
15024		}
15025
15026		// Some values can't be extracted from a
15027		// string if certain combinations are present.
15028		throwEqualError(filteredOptions, 'mark', 'thousand');
15029		throwEqualError(filteredOptions, 'prefix', 'negative');
15030		throwEqualError(filteredOptions, 'prefix', 'negativeBefore');
15031
15032		return filteredOptions;
15033	}
15034
15035	// Pass all options as function arguments
15036	function passAll ( options, method, input ) {
15037		var i, args = [];
15038
15039		// Add all options in order of FormatOptions
15040		for ( i = 0; i < FormatOptions.length; i+=1 ) {
15041			args.push(options[FormatOptions[i]]);
15042		}
15043
15044		// Append the input, then call the method, presenting all
15045		// options as arguments.
15046		args.push(input);
15047		return method.apply('', args);
15048	}
15049
15050	function wNumb ( options ) {
15051
15052		if ( !(this instanceof wNumb) ) {
15053			return new wNumb ( options );
15054		}
15055
15056		if ( typeof options !== "object" ) {
15057			return;
15058		}
15059
15060		options = validate(options);
15061
15062		// Call 'formatTo' with proper arguments.
15063		this.to = function ( input ) {
15064			return passAll(options, formatTo, input);
15065		};
15066
15067		// Call 'formatFrom' with proper arguments.
15068		this.from = function ( input ) {
15069			return passAll(options, formatFrom, input);
15070		};
15071	}
15072
15073	return wNumb;
15074
15075}));
15076
15077/*!
15078 * jQuery Form Plugin
15079 * version: 4.2.2
15080 * Requires jQuery v1.7.2 or later
15081 * Project repository: https://github.com/jquery-form/form
15082
15083 * Copyright 2017 Kevin Morris
15084 * Copyright 2006 M. Alsup
15085
15086 * Dual licensed under the LGPL-2.1+ or MIT licenses
15087 * https://github.com/jquery-form/form#license
15088
15089 * This library is free software; you can redistribute it and/or
15090 * modify it under the terms of the GNU Lesser General Public
15091 * License as published by the Free Software Foundation; either
15092 * version 2.1 of the License, or (at your option) any later version.
15093 * This library is distributed in the hope that it will be useful,
15094 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15095 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15096 * Lesser General Public License for more details.
15097 */
15098!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,r){return void 0===r&&(r="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(r),r}:e(jQuery)}(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(t.target).closest("form").ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=r.form;if(i.clk=r,"image"===r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n=/\r?\n/g,i={};i.fileapi=void 0!==e('<input type="file">').get(0).files,i.formdata=void 0!==window.FormData;var o=!!e.fn.prop;e.fn.attr2=function(){if(!o)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t,r,n,s){function u(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;a<o;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function c(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(e){a("cannot get iframe.contentWindow document: "+e)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function i(){function t(){try{var e=n(v).readyState;a("state = "+e),e&&"uninitialized"===e.toLowerCase()&&setTimeout(t,50)}catch(e){a("Server abort: ",e," (",e.name,")"),s(L),j&&clearTimeout(j),j=void 0}}var r=p.attr2("target"),i=p.attr2("action"),o=p.attr("enctype")||p.attr("encoding")||"multipart/form-data";w.setAttribute("target",m),l&&!/post/i.test(l)||w.setAttribute("method","POST"),i!==f.url&&w.setAttribute("action",f.url),f.skipEncodingOverride||l&&!/post/i.test(l)||p.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),f.timeout&&(j=setTimeout(function(){T=!0,s(A)},f.timeout));var u=[];try{if(f.extraData)for(var c in f.extraData)f.extraData.hasOwnProperty(c)&&(e.isPlainObject(f.extraData[c])&&f.extraData[c].hasOwnProperty("name")&&f.extraData[c].hasOwnProperty("value")?u.push(e('<input type="hidden" name="'+f.extraData[c].name+'">',k).val(f.extraData[c].value).appendTo(w)[0]):u.push(e('<input type="hidden" name="'+c+'">',k).val(f.extraData[c]).appendTo(w)[0]));f.iframeTarget||h.appendTo(D),v.attachEvent?v.attachEvent("onload",s):v.addEventListener("load",s,!1),setTimeout(t,15);try{w.submit()}catch(e){document.createElement("form").submit.apply(w)}}finally{w.setAttribute("action",i),w.setAttribute("enctype",o),r?w.setAttribute("target",r):p.removeAttr("target"),e(u).remove()}}function s(t){if(!x.aborted&&!X){if((O=n(v))||(a("cannot access response document"),t=L),t===A&&x)return x.abort("timeout"),void S.reject(x,"timeout");if(t===L&&x)return x.abort("server abort"),void S.reject(x,"error","server abort");if(O&&O.location.href!==f.iframeSrc||T){v.detachEvent?v.detachEvent("onload",s):v.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"===f.dataType||O.XMLDocument||e.isXMLDoc(O);if(a("isXml="+o),!o&&window.opera&&(null===O.body||!O.body.innerHTML)&&--C)return a("requeing onLoad callback, DOM not available"),void setTimeout(s,250);var u=O.body?O.body:O.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=O.XMLDocument?O.XMLDocument:O,o&&(f.dataType="xml"),x.getResponseHeader=function(e){return{"content-type":f.dataType}[e.toLowerCase()]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var c=(f.dataType||"").toLowerCase(),l=/(json|script|text)/.test(c);if(l||f.textarea){var p=O.getElementsByTagName("textarea")[0];if(p)x.responseText=p.value,x.status=Number(p.getAttribute("status"))||x.status,x.statusText=p.getAttribute("statusText")||x.statusText;else if(l){var m=O.getElementsByTagName("pre")[0],g=O.getElementsByTagName("body")[0];m?x.responseText=m.textContent?m.textContent:m.innerText:g&&(x.responseText=g.textContent?g.textContent:g.innerText)}}else"xml"===c&&!x.responseXML&&x.responseText&&(x.responseXML=q(x.responseText));try{M=N(x,c,f)}catch(e){i="parsererror",x.error=r=e||i}}catch(e){a("error caught: ",e),i="error",x.error=r=e||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&x.status<300||304===x.status?"success":"error"),"success"===i?(f.success&&f.success.call(f.context,M,"success",x),S.resolve(x.responseText,"success",x),d&&e.event.trigger("ajaxSuccess",[x,f])):i&&(void 0===r&&(r=x.statusText),f.error&&f.error.call(f.context,x,i,r),S.reject(x,"error",r),d&&e.event.trigger("ajaxError",[x,f,r])),d&&e.event.trigger("ajaxComplete",[x,f]),d&&!--e.active&&e.event.trigger("ajaxStop"),f.complete&&f.complete.call(f.context,x,i),X=!0,f.timeout&&clearTimeout(j),setTimeout(function(){f.iframeTarget?h.attr("src",f.iframeSrc):h.remove(),x.responseXML=null},100)}}}var u,c,f,d,m,h,v,x,y,b,T,j,w=p[0],S=e.Deferred();if(S.abort=function(e){x.abort(e)},r)for(c=0;c<g.length;c++)u=e(g[c]),o?u.prop("disabled",!1):u.removeAttr("disabled");(f=e.extend(!0,{},e.ajaxSettings,t)).context=f.context||f,m="jqFormIO"+(new Date).getTime();var k=w.ownerDocument,D=p.closest("body");if(f.iframeTarget?(b=(h=e(f.iframeTarget,k)).attr2("name"))?m=b:h.attr2("name",m):(h=e('<iframe name="'+m+'" src="'+f.iframeSrc+'" />',k)).css({position:"absolute",top:"-1000px",left:"-1000px"}),v=h[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{v.contentWindow.document.execCommand&&v.contentWindow.document.execCommand("Stop")}catch(e){}h.attr("src",f.iframeSrc),x.error=r,f.error&&f.error.call(f.context,x,r,t),d&&e.event.trigger("ajaxError",[x,f,r]),f.complete&&f.complete.call(f.context,x,r)}},(d=f.global)&&0==e.active++&&e.event.trigger("ajaxStart"),d&&e.event.trigger("ajaxSend",[x,f]),f.beforeSend&&!1===f.beforeSend.c
15098all(f.context,x,f))return f.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;(y=w.clk)&&(b=y.name)&&!y.disabled&&(f.extraData=f.extraData||{},f.extraData[b]=y.value,"image"===y.type&&(f.extraData[b+".x"]=w.clk_x,f.extraData[b+".y"]=w.clk_y));var A=1,L=2,F=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&F&&(f.extraData=f.extraData||{},f.extraData[E]=F),f.forceSync?i():setTimeout(i,10);var M,O,X,C=50,q=e.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},_=e.parseJSON||function(e){return window.eval("("+e+")")},N=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i=("xml"===r||!r)&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&(("json"===r||!r)&&n.indexOf("json")>=0?o=_(o):("script"===r||!r)&&n.indexOf("javascript")>=0&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var l,f,d,p=this;"function"==typeof t?t={success:t}
15098:"string"==typeof t||!1===t&&arguments.length>0?(t={url:t,data:r,dataType:n},"function"==typeof s&&(t.success=s)):void 0===t&&(t={}),l=t.method||t.type||this.attr2("method"),(d=(d="string"==typeof(f=t.url||this.attr2("action"))?e.trim(f):"")||window.location.href||"")&&(d=(d.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:d,success:e.ajaxSettings.success,type:l||e.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&!1===t.beforeSerialize(this,t))return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var h=t.traditional;void 0===h&&(h=e.ajaxSettings.traditional);var v,g=[],x=this.formToArray(t.semantic,g,t.filtering);if(t.data){var y=e.isFunction(t.data)?t.data(x):t.data;t.extraData=y,v=e.param(y,h)}if(t.beforeSubmit&&!1===t.beforeSubmit(x,this,t))return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[x,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var b=e.param(x,h);v&&(b=b?b+"&"+v:v),"GET"===t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+b,t.data=null):t.data=b;var T=[];
15098if(t.resetForm&&T.push(function(){p.resetForm()}),t.clearForm&&T.push(function(){p.clearForm(t.includeHidden)}),!t.dataType&&t.target){var j=t.success||function(){};T.push(function(r,a,n){var i=arguments,o=t.replaceTarget?"replaceWith":"html";e(t.target)[o](r).each(function(){j.apply(this,i)})})}else t.success&&(e.isArray(t.success)?e.merge(T,t.success):T.push(t.success));if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=T.length;i<o;i++)T[i].apply(n,[e,r,a||p,p])},t.error){var w=t.error;t.error=function(e,r,a){var n=t.context||this;w.apply(n,[e,r,a,p])}}if(t.complete){var S=t.complete;t.complete=function(e,r){var a=t.context||this;S.apply(a,[e,r,p])}}var k=e("input[type=file]:enabled",this).filter(function(){return""!==e(this).val()}).length>0,D="multipart/form-data",A=p.attr("enctype")===D||p.attr("encoding")===D,L=i.fileapi&&i.formdata;a("fileAPI :"+L);var F,E=(k||A)&&!L;!1!==t.iframe&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){F=c(x)}):F=c(x):F=(k||A)&&L?function(r){for(var a=new FormData,n=0;n<r.length;n++)a.append(r[n].name,r[n].value);if(t.extraData){var i=u(t.extraData);for(n=0;n<i.length;n++)i[n]&&a.append(i[n][0],i[n][1])}t.data=null;var o=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:l||"POST"});t.uploadProgress&&(o.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(a/n*100)),t.uploadProgress(e,a,n,r)},!1),r}),o.data=null;var s=o.beforeSend;return o.beforeSend=function(e,r){t.formData?r.data=t.formData:r.data=a,s&&s.call(this,e,r)},e.ajax(o)}(x):e.ajax(t),p.removeData("jqxhr").data("jqxhr",F);for(var M=0;M<g.length;M++)g[M]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n,i,o,s){if(("string"==typeof n||!1===n&&arguments.length>0)&&(n={url:n,data:i,dataType:o},"function"==typeof s&&(n.success=s)),n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var u={s:this.selector,c:this.context};return!e.isReady&&u.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(u.s,u.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().on("submit.form-plugin",n,t).on("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r,a){var n=[];if(0===this.length)return n;var o,s=this[0],u=this.attr("id"),c=t||void 0===s.elements?s.getElementsByTagName("*"):s.elements;if(c&&(c=e.makeArray(c)),u&&(t||/(Edge|Trident)\//.test(navigator.userAgent))&&(o=e(':input[form="'+u+'"]').get()).length&&(c=(c||[]).concat(o)),!c||!c.length)return n;e.isFunction(a)&&(c=e.map(c,a));var l,f,d,p,m,h,v;for(l=0,h=c.length;l<h;l++)if(m=c[l],(d=m.name)&&!m.disabled)if(t&&s.clk&&"image"===m.type)s.clk===m&&(n.push({name:d,value:e(m).val(),type:m.type}),n.push({name:d+".x",value:s.clk_x},{name:d+".y",value:s.clk_y}));else if((p=e.fieldValue(m,!0))&&p.constructor===Array)for(r&&r.push(m),f=0,v=p.length;f<v;f++)n.push({name:d,value:p[f]});else if(i.fileapi&&"file"===m.type){r&&r.push(m);var g=m.files;if(g.length)for(f=0;f<g.length;f++)n.push({name:d,value:g[f],type:m.type});else n.push({name:d,value:"",type:m.type})}else null!==p&&void 0!==p&&(r&&r.push(m),n.push({name:d,value:p,type:m.type,required:m.required}));if(!t&&s.clk){var x=e(s.clk),y=x[0];(d=y.name)&&!y.disabled&&"image"===y.type&&(n.push({name:d,value:x.val()}),n.push({name:d+".x",value:s.clk_x},{name:d+".y",value:s.clk_y}))}return n},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor===Array)for(var i=0,o=n.length;i<o;i++)r.push({name:a,value:n[i]});else null!==n&&void 0!==n&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;a<n;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor===Array&&!o.length||(o.constructor===Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,i=t.type,o=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"===i||"button"===i||("checkbox"===i||"radio"===i)&&!t.checked||("submit"===i||"image"===i)&&t.form&&t.form.clk!==t||"select"===o&&-1===t.selectedIndex))return null;if("select"===o){var s=t.selectedIndex;if(s<0)return null;for(var u=[],c=t.options,l="select-one"===i,f=l?s+1:c.length,d=l?s:0;d<f;d++){var p=c[d];if(p.selected&&!p.disabled){var m=p.value;if(m||(m=p.attributes&&p.attributes.value&&!p.attributes.value.specified?p.text:p.value),l)return m;u.push(m)}}return u}return e(t).val().replace(n,"\r\n")},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"===n?this.value="":"checkbox"===a||"radio"===a?this.checked=!1:"select"===n?this.selectedIndex=-1:"file"===a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(!0===t&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")}
15098)},e.fn.resetForm=function(){return this.each(function(){var t=e(this),r=this.tagName.toLowerCase();switch(r){case"input":this.checked=this.defaultChecked;case"textarea":return this.value=this.defaultValue,!0;case"option":case"optgroup":var a=t.parents("select");return a.length&&a[0].multiple?"option"===r?this.selected=this.defaultSelected:t.find("option").resetForm():a.resetForm(),!0;case"select":return t.find("option").each(function(e){if(this.selected=this.defaultSelected,this.defaultSelected&&!t[0].multiple)return t[0].selectedIndex=e,!1}),!0;case"label":var n=e(t.attr("for")),i=t.find("input,select,textarea");return n[0]&&i.unshift(n[0]),i.resetForm(),!0;case"form":return("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset(),!0;default:return t.find("form,input,label,select,textarea").resetForm(),!0}})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"===r||"radio"===r)this.checked=t;else if("option"===this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"===a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1});
15099//# sourceMappingURL=jquery.form.min.js.map
15100
15101/*!
15102 * jQuery blockUI plugin
15103 * Version 2.70.0-2014.11.23
15104 * Requires jQuery v1.7 or later
15105 *
15106 * Examples at: http://malsup.com/jquery/block/
15107 * Copyright (c) 2007-2013 M. Alsup
15108 * Dual licensed under the MIT and GPL licenses:
15109 * http://www.opensource.org/licenses/mit-license.php
15110 * http://www.gnu.org/licenses/gpl.html
15111 *
15112 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
15113 */
15114
15115;(function() {
15116/*jshint eqeqeq:false curly:false latedef:false */
15117"use strict";
15118
15119	function setup($) {
15120		$.fn._fadeIn = $.fn.fadeIn;
15121
15122		var noOp = $.noop || function() {};
15123
15124		// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
15125		// confusing userAgent strings on Vista)
15126		var msie = /MSIE/.test(navigator.userAgent);
15127		var ie6  = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
15128		var mode = document.documentMode || 0;
15129		var setExpr = $.isFunction( document.createElement('div').style.setExpression );
15130
15131		// global $ methods for blocking/unblocking the entire page
15132		$.blockUI   = function(opts) { install(window, opts); };
15133		$.unblockUI = function(opts) { remove(window, opts); };
15134
15135		// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
15136		$.growlUI = function(title, message, timeout, onClose) {
15137			var $m = $('<div class="growlUI"></div>');
15138			if (title) $m.append('<h1>'+title+'</h1>');
15139			if (message) $m.append('<h2>'+message+'</h2>');
15140			if (timeout === undefined) timeout = 3000;
15141
15142			// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
15143			var callBlock = function(opts) {
15144				opts = opts || {};
15145
15146				$.blockUI({
15147					message: $m,
15148					fadeIn : typeof opts.fadeIn  !== 'undefined' ? opts.fadeIn  : 700,
15149					fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
15150					timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
15151					centerY: false,
15152					showOverlay: false,
15153					onUnblock: onClose,
15154					css: $.blockUI.defaults.growlCSS
15155				});
15156			};
15157
15158			callBlock();
15159			var nonmousedOpacity = $m.css('opacity');
15160			$m.mouseover(function() {
15161				callBlock({
15162					fadeIn: 0,
15163					timeout: 30000
15164				});
15165
15166				var displayBlock = $('.blockMsg');
15167				displayBlock.stop(); // cancel fadeout if it has started
15168				displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
15169			}).mouseout(function() {
15170				$('.blockMsg').fadeOut(1000);
15171			});
15172			// End konapun additions
15173		};
15174
15175		// plugin method for blocking element content
15176		$.fn.block = function(opts) {
15177			if ( this[0] === window ) {
15178				$.blockUI( opts );
15179				return this;
15180			}
15181			var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
15182			this.each(function() {
15183				var $el = $(this);
15184				if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
15185					return;
15186				$el.unblock({ fadeOut: 0 });
15187			});
15188
15189			return this.each(function() {
15190				if ($.css(this,'position') == 'static') {
15191					this.style.position = 'relative';
15192					$(this).data('blockUI.static', true);
15193				}
15194				this.style.zoom = 1; // force 'hasLayout' in ie
15195				install(this, opts);
15196			});
15197		};
15198
15199		// plugin method for unblocking element content
15200		$.fn.unblock = function(opts) {
15201			if ( this[0] === window ) {
15202				$.unblockUI( opts );
15203				return this;
15204			}
15205			return this.each(function() {
15206				remove(this, opts);
15207			});
15208		};
15209
15210		$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
15211
15212		// override these in your code to change the default behavior and style
15213		$.blockUI.defaults = {
15214			// message displayed when blocking (use null for no message)
15215			message:  '<h1>Please wait...</h1>',
15216
15217			title: null,		// title string; only used when theme == true
15218			draggable: true,	// only used when theme == true (requires jquery-ui.js to be loaded)
15219
15220			theme: false, // set to true to use with jQuery UI themes
15221
15222			// styles for the message when blocking; if you wish to disable
15223			// these and use an external stylesheet then do this in your code:
15224			// $.blockUI.defaults.css = {};
15225			css: {
15226				padding:	0,
15227				margin:		0,
15228				width:		'30%',
15229				top:		'40%',
15230				left:		'35%',
15231				textAlign:	'center',
15232				color:		'#000',
15233				border:		'3px solid #aaa',
15234				backgroundColor:'#fff',
15235				cursor:		'wait'
15236			},
15237
15238			// minimal style set used when themes are used
15239			themedCSS: {
15240				width:	'30%',
15241				top:	'40%',
15242				left:	'35%'
15243			},
15244
15245			// styles for the overlay
15246			overlayCSS:  {
15247				backgroundColor:	'#000',
15248				opacity:			0.6,
15249				cursor:				'wait'
15250			},
15251
15252			// style to replace wait cursor before unblocking to correct issue
15253			// of lingering wait cursor
15254			cursorReset: 'default',
15255
15256			// styles applied when using $.growlUI
15257			growlCSS: {
15258				width:		'350px',
15259				top:		'10px',
15260				left:		'',
15261				right:		'10px',
15262				border:		'none',
15263				padding:	'5px',
15264				opacity:	0.6,
15265				cursor:		'default',
15266				color:		'#fff',
15267				backgroundColor: '#000',
15268				'-webkit-border-radius':'10px',
15269				'-moz-border-radius':	'10px',
15270				'border-radius':		'10px'
15271			},
15272
15273			// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
15274			// (hat tip to Jorge H. N. de Vasconcelos)
15275			/*jshint scripturl:true */
15276			iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
15277
15278			// force usage of iframe in non-IE browsers (handy for blocking applets)
15279			forceIframe: false,
15280
15281			// z-index for the blocking overlay
15282			baseZ: 1000,
15283
15284			// set these to true to have the message automatically centered
15285			centerX: true, // <-- only effects element blocking (page block controlled via css above)
15286			centerY: true,
15287
15288			// allow body element to be stetched in ie6; this makes blocking look better
15289			// on "short" pages.  disable if you wish to prevent changes to the body height
15290			allowBodyStretch: true,
15291
15292			// enable if you want key and mouse events to be disabled for content that is blocked
15293			bindEvents: true,
15294
15295			// be default blockUI will supress tab navigation from leaving blocking content
15296			// (if bindEvents is true)
15297			constrainTabKey: true,
15298
15299			// fadeIn time in millis; set to 0 to disable fadeIn on block
15300			fadeIn:  200,
15301
15302			// fadeOut time in millis; set to 0 to disable fadeOut on unblock
15303			fadeOut:  400,
15304
15305			// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
15306			timeout: 0,
15307
15308			// disable if you don't want to show the overlay
15309			showOverlay: true,
15310
15311			// if true, focus will be placed in the first available input field when
15312			// page blocking
15313			focusInput: true,
15314
15315            // elements that can receive focus
15316            focusableElements: ':input:enabled:visible',
15317
15318			// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
15319			// no longer needed in 2012
15320			// applyPlatformOpacityRules: true,
15321
15322			// callback method invoked when fadeIn has completed and blocking message is visible
15323			onBlock: null,
15324
15325			// callback method invoked when unblocking has completed; the callback is
15326			// passed the element that has been unblocked (which is the window object for page
15327			// blocks) and the options that were passed to the unblock call:
15328			//	onUnblock(element, options)
15329			onUnblock: null,
15330
15331			// callback method invoked when the overlay area is clicked.
15332			// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
15333			onOverlayClick: null,
15334
15335			// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
vendor: 11,306 bytes, lines 15336-15673
15336			quirksmodeOffsetHack: 4,
15337
15338			// class name of the message block
15339			blockMsgClass: 'blockMsg',
15340
15341			// if it is already blocked, then ignore it (don't unblock and reblock)
15342			ignoreIfBlocked: false
15343		};
15344
15345		// private data and functions follow...
15346
15347		var pageBlock = null;
15348		var pageBlockEls = [];
15349
15350		function install(el, opts) {
15351			var css, themedCSS;
15352			var full = (el == window);
15353			var msg = (opts && opts.message !== undefined ? opts.message : undefined);
15354			opts = $.extend({}, $.blockUI.defaults, opts || {});
15355
15356			if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
15357				return;
15358
15359			opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
15360			css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
15361			if (opts.onOverlayClick)
15362				opts.overlayCSS.cursor = 'pointer';
15363
15364			themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
15365			msg = msg === undefined ? opts.message : msg;
15366
15367			// remove the current block (if there is one)
15368			if (full && pageBlock)
15369				remove(window, {fadeOut:0});
15370
15371			// if an existing element is being used as the blocking content then we capture
15372			// its current place in the DOM (and current display style) so we can restore
15373			// it when we unblock
15374			if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
15375				var node = msg.jquery ? msg[0] : msg;
15376				var data = {};
15377				$(el).data('blockUI.history', data);
15378				data.el = node;
15379				data.parent = node.parentNode;
15380				data.display = node.style.display;
15381				data.position = node.style.position;
15382				if (data.parent)
15383					data.parent.removeChild(node);
15384			}
15385
15386			$(el).data('blockUI.onUnblock', opts.onUnblock);
15387			var z = opts.baseZ;
15388
15389			// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
15390			// layer1 is the iframe layer which is used to supress bleed through of underlying content
15391			// layer2 is the overlay layer which has opacity and a wait cursor (by default)
15392			// layer3 is the message content that is displayed while blocking
15393			var lyr1, lyr2, lyr3, s;
15394			if (msie || opts.forceIframe)
15395				lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
15396			else
15397				lyr1 = $('<div class="blockUI" style="display:none"></div>');
15398
15399			if (opts.theme)
15400				lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
15401			else
15402				lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
15403
15404			if (opts.theme && full) {
15405				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
15406				if ( opts.title ) {
15407					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
15408				}
15409				s += '<div class="ui-widget-content ui-dialog-content"></div>';
15410				s += '</div>';
15411			}
15412			else if (opts.theme) {
15413				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
15414				if ( opts.title ) {
15415					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
15416				}
15417				s += '<div class="ui-widget-content ui-dialog-content"></div>';
15418				s += '</div>';
15419			}
15420			else if (full) {
15421				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
15422			}
15423			else {
15424				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
15425			}
15426			lyr3 = $(s);
15427
15428			// if we have a message, style it
15429			if (msg) {
15430				if (opts.theme) {
15431					lyr3.css(themedCSS);
15432					lyr3.addClass('ui-widget-content');
15433				}
15434				else
15435					lyr3.css(css);
15436			}
15437
15438			// style the overlay
15439			if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
15440				lyr2.css(opts.overlayCSS);
15441			lyr2.css('position', full ? 'fixed' : 'absolute');
15442
15443			// make iframe layer transparent in IE
15444			if (msie || opts.forceIframe)
15445				lyr1.css('opacity',0.0);
15446
15447			//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
15448			var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
15449			$.each(layers, function() {
15450				this.appendTo($par);
15451			});
15452
15453			if (opts.theme && opts.draggable && $.fn.draggable) {
15454				lyr3.draggable({
15455					handle: '.ui-dialog-titlebar',
15456					cancel: 'li'
15457				});
15458			}
15459
15460			// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
15461			var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
15462			if (ie6 || expr) {
15463				// give body 100% height
15464				if (full && opts.allowBodyStretch && $.support.boxModel)
15465					$('html,body').css('height','100%');
15466
15467				// fix ie6 issue when blocked element has a border width
15468				if ((ie6 || !$.support.boxModel) && !full) {
15469					var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
15470					var fixT = t ? '(0 - '+t+')' : 0;
15471					var fixL = l ? '(0 - '+l+')' : 0;
15472				}
15473
15474				// simulate fixed position
15475				$.each(layers, function(i,o) {
15476					var s = o[0].style;
15477					s.position = 'absolute';
15478					if (i < 2) {
15479						if (full)
15480							s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
15481						else
15482							s.setExpression('height','this.parentNode.offsetHeight + "px"');
15483						if (full)
15484							s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
15485						else
15486							s.setExpression('width','this.parentNode.offsetWidth + "px"');
15487						if (fixL) s.setExpression('left', fixL);
15488						if (fixT) s.setExpression('top', fixT);
15489					}
15490					else if (opts.centerY) {
15491						if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
15492						s.marginTop = 0;
15493					}
15494					else if (!opts.centerY && full) {
15495						var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
15496						var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
15497						s.setExpression('top',expression);
15498					}
15499				});
15500			}
15501
15502			// show the message
15503			if (msg) {
15504				if (opts.theme)
15505					lyr3.find('.ui-widget-content').append(msg);
15506				else
15507					lyr3.append(msg);
15508				if (msg.jquery || msg.nodeType)
15509					$(msg).show();
15510			}
15511
15512			if ((msie || opts.forceIframe) && opts.showOverlay)
15513				lyr1.show(); // opacity is zero
15514			if (opts.fadeIn) {
15515				var cb = opts.onBlock ? opts.onBlock : noOp;
15516				var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
15517				var cb2 = msg ? cb : noOp;
15518				if (opts.showOverlay)
15519					lyr2._fadeIn(opts.fadeIn, cb1);
15520				if (msg)
15521					lyr3._fadeIn(opts.fadeIn, cb2);
15522			}
15523			else {
15524				if (opts.showOverlay)
15525					lyr2.show();
15526				if (msg)
15527					lyr3.show();
15528				if (opts.onBlock)
15529					opts.onBlock.bind(lyr3)();
15530			}
15531
15532			// bind key and mouse events
15533			bind(1, el, opts);
15534
15535			if (full) {
15536				pageBlock = lyr3[0];
15537				pageBlockEls = $(opts.focusableElements,pageBlock);
15538				if (opts.focusInput)
15539					setTimeout(focus, 20);
15540			}
15541			else
15542				center(lyr3[0], opts.centerX, opts.centerY);
15543
15544			if (opts.timeout) {
15545				// auto-unblock
15546				var to = setTimeout(function() {
15547					if (full)
15548						$.unblockUI(opts);
15549					else
15550						$(el).unblock(opts);
15551				}, opts.timeout);
15552				$(el).data('blockUI.timeout', to);
15553			}
15554		}
15555
15556		// remove the block
15557		function remove(el, opts) {
15558			var count;
15559			var full = (el == window);
15560			var $el = $(el);
15561			var data = $el.data('blockUI.history');
15562			var to = $el.data('blockUI.timeout');
15563			if (to) {
15564				clearTimeout(to);
15565				$el.removeData('blockUI.timeout');
15566			}
15567			opts = $.extend({}, $.blockUI.defaults, opts || {});
15568			bind(0, el, opts); // unbind events
15569
15570			if (opts.onUnblock === null) {
15571				opts.onUnblock = $el.data('blockUI.onUnblock');
15572				$el.removeData('blockUI.onUnblock');
15573			}
15574
15575			var els;
15576			if (full) // crazy selector to handle odd field errors in ie6/7
15577				els = $('body').children().filter('.blockUI').add('body > .blockUI');
15578			else
15579				els = $el.find('>.blockUI');
15580
15581			// fix cursor issue
15582			if ( opts.cursorReset ) {
15583				if ( els.length > 1 )
15584					els[1].style.cursor = opts.cursorReset;
15585				if ( els.length > 2 )
15586					els[2].style.cursor = opts.cursorReset;
15587			}
15588
15589			if (full)
15590				pageBlock = pageBlockEls = null;
15591
15592			if (opts.fadeOut) {
15593				count = els.length;
15594				els.stop().fadeOut(opts.fadeOut, function() {
15595					if ( --count === 0)
15596						reset(els,data,opts,el);
15597				});
15598			}
15599			else
15600				reset(els, data, opts, el);
15601		}
15602
15603		// move blocking element back into the DOM where it started
15604		function reset(els,data,opts,el) {
15605			var $el = $(el);
15606			if ( $el.data('blockUI.isBlocked') )
15607				return;
15608
15609			els.each(function(i,o) {
15610				// remove via DOM calls so we don't lose event handlers
15611				if (this.parentNode)
15612					this.parentNode.removeChild(this);
15613			});
15614
15615			if (data && data.el) {
15616				data.el.style.display = data.display;
15617				data.el.style.position = data.position;
15618				data.el.style.cursor = 'default'; // #59
15619				if (data.parent)
15620					data.parent.appendChild(data.el);
15621				$el.removeData('blockUI.history');
15622			}
15623
15624			if ($el.data('blockUI.static')) {
15625				$el.css('position', 'static'); // #22
15626			}
15627
15628			if (typeof opts.onUnblock == 'function')
15629				opts.onUnblock(el,opts);
15630
15631			// fix issue in Safari 6 where block artifacts remain until reflow
15632			var body = $(document.body), w = body.width(), cssW = body[0].style.width;
15633			body.width(w-1).width(w);
15634			body[0].style.width = cssW;
15635		}
15636
15637		// bind/unbind the handler
15638		function bind(b, el, opts) {
15639			var full = el == window, $el = $(el);
15640
15641			// don't bother unbinding if there is nothing to unbind
15642			if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
15643				return;
15644
15645			$el.data('blockUI.isBlocked', b);
15646
15647			// don't bind events when overlay is not in use or if bindEvents is false
15648			if (!full || !opts.bindEvents || (b && !opts.showOverlay))
15649				return;
15650
15651			// bind anchors and inputs for mouse and key events
15652			var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
15653			if (b)
15654				$(document).bind(events, opts, handler);
15655			else
15656				$(document).unbind(events, handler);
15657
15658		// former impl...
15659		//		var $e = $('a,:input');
15660		//		b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
15661		}
15662
15663		// event handler to suppress keyboard/mouse events when blocking
15664		function handler(e) {
15665			// allow tab navigation (conditionally)
15666			if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
15667				if (pageBlock && e.data.constrainTabKey) {
15668					var els = pageBlockEls;
15669					var fwd = !e.shiftKey && e.target === els[els.length-1];
15670					var back = e.shiftKey && e.target === els[0];
15671					if (fwd || back) {
15672						setTimeout(function(){focus(back);},10);
15673						return false;
15674					}
15675				}
15676			}
15677			var opts = e.data;
15678			var target = $(e.target);
15679			if (target.hasClass('blockOverlay') && opts.onOverlayClick)
15680				opts.onOverlayClick(e);
15681
15682			// allow events within the message content
15683			if (target.parents('div.' + opts.blockMsgClass).length > 0)
15684				return true;
15685
15686			// allow events for content that is not being blocked
15687			return target.parents().children().filter('div.blockUI').length === 0;
15688		}
15689
15690		function focus(back) {
15691			if (!pageBlockEls)
15692				return;
15693			var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
15694			if (e)
15695				e.focus();
15696		}
15697
15698		function center(el, x, y) {
15699			var p = el.parentNode, s = el.style;
15700			var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
15701			var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
15702			if (x) s.left = l > 0 ? (l+'px') : '0';
15703			if (y) s.top  = t > 0 ? (t+'px') : '0';
15704		}
15705
15706		function sz(el, p) {
15707			return parseInt($.css(el,p),10)||0;
15708		}
15709
15710	}
15711
15712
15713	/*global define:true */
15714	if (typeof define === 'function' && define.amd) {
15715		// AMD. Register as an anonymous module.
15716		define(['jquery'], setup);
15717	} else if (typeof exports === 'object') {
15718		// Node/CommonJS
15719		setup(require('jquery'));
15720	} else {
15721		// Browser globals
15722		setup(jQuery);
15723	}
15724
15725})();
15726
15727/*!
15728 * Datepicker for Bootstrap v1.9.0 (https://github.com/uxsolutions/bootstrap-datepicker)
15729 *
15730 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
15731 */
15732
15733!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a,b){function c(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var a=new Date;return c(a.getFullYear(),a.getMonth(),a.getDate())}function e(a,b){return a.getUTCFullYear()===b.getUTCFullYear()&&a.getUTCMonth()===b.getUTCMonth()&&a.getUTCDate()===b.getUTCDate()}function f(c,d){return function(){return d!==b&&a.fn.datepicker.deprecated(d),this[c].apply(this,arguments)}}function g(a){return a&&!isNaN(a.getTime())}function h(b,c){function d(a,b){return b.toLowerCase()}var e,f=a(b).data(),g={},h=new RegExp("^"+c.toLowerCase()+"([A-Z])");c=new RegExp("^"+c.toLowerCase());for(var i in f)c.test(i)&&(e=i.replace(h,d),g[e]=f[i]);return g}function i(b){var c={};if(q[b]||(b=b.split("-")[0],q[b])){var d=q[b];return a.each(p,function(a,b){b in d&&(c[b]=d[b])}),c}}var j=function(){var b={get:function(a){return this.slice(a)[0]},contains:function(a){for(var b=a&&a.valueOf(),c=0,d=this.length;c<d;c++)if(0<=this[c].valueOf()-b&&this[c].valueOf()-b<864e5)return c;return-1},remove:function(a){this.splice(a,1)},replace:function(b){b&&(a.isArray(b)||(b=[b]),this.clear(),this.push.apply(this,b))},clear:function(){this.length=0},copy:function(){var a=new j;return a.replace(this),a}};return function(){var c=[];return c.push.apply(c,arguments),a.extend(c,b),c}}(),k=function(b,c){a.data(b,"datepicker",this),this._events=[],this._secondaryEvents=[],this._process_options(c),this.dates=new j,this.viewDate=this.o.defaultViewDate,this.focusDate=null,this.element=a(b),this.isInput=this.element.is("input"),this.inputField=this.isInput?this.element:this.element.find("input"),this.component=!!this.element.hasClass("date")&&this.element.find(".add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn"),this.component&&0===this.component.length&&(this.component=!1),this.isInline=!this.component&&this.element.is("div"),this.picker=a(r.template),this._check_template(this.o.templates.leftArrow)&&this.picker.find(".prev").html(this.o.templates.leftArrow),this._check_template(this.o.templates.rightArrow)&&this.picker.find(".next").html(this.o.templates.rightArrow),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&this.picker.addClass("datepicker-rtl"),this.o.calendarWeeks&&this.picker.find(".datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear").attr("colspan",function(a,b){return Number(b)+1}
vendor: 13,629 bytes, line 15733
15733),this._process_options({startDate:this._o.startDate,endDate:this._o.endDate,daysOfWeekDisabled:this.o.daysOfWeekDisabled,daysOfWeekHighlighted:this.o.daysOfWeekHighlighted,datesDisabled:this.o.datesDisabled}),this._allow_update=!1,this.setViewMode(this.o.startView),this._allow_update=!0,this.fillDow(),this.fillMonths(),this.update(),this.isInline&&this.show()};k.prototype={constructor:k,_resolveViewName:function(b){return a.each(r.viewModes,function(c,d){if(b===c||-1!==a.inArray(b,d.names))return b=c,!1}),b},_resolveDaysOfWeek:function(b){return a.isArray(b)||(b=b.split(/[,\s]*/)),a.map(b,Number)},_check_template:function(c){try{if(c===b||""===c)return!1;if((c.match(/[<>]/g)||[]).length<=0)return!0;return a(c).length>0}catch(a){return!1}},_process_options:function(b){this._o=a.extend({},this._o,b);var e=this.o=a.extend({},this._o),f=e.language;q[f]||(f=f.split("-")[0],q[f]||(f=o.language)),e.language=f,e.startView=this._resolveViewName(e.startView),e.minViewMode=this._resolveViewName(e.minViewMode),e.maxViewMode=this._resolveViewName(e.maxViewMode),e.startView=Math.max(this.o.minViewMode,Math.min(this.o.maxViewMode,e.startView)),!0!==e.multidate&&(e.multidate=Number(e.multidate)||!1,!1!==e.multidate&&(e.multidate=Math.max(0,e.multidate))),e.multidateSeparator=String(e.multidateSeparator),e.weekStart%=7,e.weekEnd=(e.weekStart+6)%7;var g=r.parseFormat(e.format);e.startDate!==-1/0&&(e.startDate?e.startDate instanceof Date?e.startDate=this._local_to_utc(this._zero_time(e.startDate)):e.startDate=r.parseDate(e.startDate,g,e.language,e.assumeNearbyYear):e.startDate=-1/0),e.endDate!==1/0&&(e.endDate?e.endDate instanceof Date?e.endDate=this._local_to_utc(this._zero_time(e.endDate)):e.endDate=r.parseDate(e.endDate,g,e.language,e.assumeNearbyYear):e.endDate=1/0),e.daysOfWeekDisabled=this._resolveDaysOfWeek(e.daysOfWeekDisabled||[]),e.daysOfWeekHighlighted=this._resolveDaysOfWeek(e.daysOfWeekHighlighted||[]),e.datesDisabled=e.datesDisabled||[],a.isArray(e.datesDisabled)||(e.datesDisabled=e.datesDisabled.split(",")),e.datesDisabled=a.map(e.datesDisabled,function(a){return r.parseDate(a,g,e.language,e.assumeNearbyYear)});var h=String(e.orientation).toLowerCase().split(/\s+/g),i=e.orientation.toLowerCase();if(h=a.grep(h,function(a){return/^auto|left|right|top|bottom$/.test(a)}),e.orientation={x:"auto",y:"auto"},i&&"auto"!==i)if(1===h.length)switch(h[0]){case"top":case"bottom":e.orientation.y=h[0];break;case"left":case"right":e.orientation.x=h[0]}else i=a.grep(h,function(a){return/^left|right$/.test(a)}),e.orientation.x=i[0]||"auto",i=a.grep(h,function(a){return/^top|bottom$/.test(a)}),e.orientation.y=i[0]||"auto";else;if(e.defaultViewDate instanceof Date||"string"==typeof e.defaultViewDate)e.defaultViewDate=r.parseDate(e.defaultViewDate,g,e.language,e.assumeNearbyYear);else if(e.defaultViewDate){var j=e.defaultViewDate.year||(new Date).getFullYear(),k=e.defaultViewDate.month||0,l=e.defaultViewDate.day||1;e.defaultViewDate=c(j,k,l)}else e.defaultViewDate=d()},_applyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(d=b,e=a[f][1]):3===a[f].length&&(d=a[f][1],e=a[f][2]),c.on(e,d)},_unapplyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(e=b,d=a[f][1]):3===a[f].length&&(e=a[f][1],d=a[f][2]),c.off(d,e)},_buildEvents:function(){var b={keyup:a.proxy(function(b){-1===a.inArray(b.keyCode,[27,37,39,38,40,32,13,9])&&this.update()},this),keydown:a.proxy(this.keydown,this),paste:a.proxy(this.paste,this)};!0===this.o.showOnFocus&&(b.focus=a.proxy(this.show,this)),this.isInput?this._events=[[this.element,b]]:this.component&&this.inputField.length?this._events=[[this.inputField,b],[this.component,{click:a.proxy(this.show,this)}]]:this._events=[[this.element,{click:a.proxy(this.show,this),keydown:a.proxy(this.keydown,this)}]],this._events.push([this.element,"*",{blur:a.proxy(function(a){this._focused_from=a.target},this)}],[this.element,{blur:a.proxy(function(a){this._focused_from=a.target},this)}]),this.o.immediateUpdates&&this._events.push([this.element,{"changeYear changeMonth":a.proxy(function(a){this.update(a.date)},this)}]),this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[this.picker,".prev, .next",{click:a.proxy(this.navArrowsClick,this)}],[this.picker,".day:not(.disabled)",{click:a.proxy(this.dayCellClick,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{"mousedown touchstart":a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).length||this.picker.is(a.target)||this.picker.find(a.target).length||this.isInline||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.dates.get(-1),e=this._utc_to_local(d);this.element.trigger({type:b,date:e,viewMode:this.viewMode,dates:a.map(this.dates,this._utc_to_local),format:a.proxy(function(a,b){0===arguments.length?(a=this.dates.length-1,b=this.o.format):"string"==typeof a&&(b=a,a=this.dates.length-1),b=b||this.o.format;var c=this.dates.get(a);return r.formatDate(c,b,this.o.language)},this)})},show:function(){if(!(this.inputField.is(":disabled")||this.inputField.prop("readonly")&&!1===this.o.enableOnReadonly))return this.isInline||this.picker.appendTo(this.o.container),this.place(),this.picker.show(),this._attachSecondaryEvents(),this._trigger("show"),(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&this.o.disableTouchKeyboard&&a(this.element).blur(),this},hide:function(){return this.isInline||!this.picker.is(":visible")?this:(this.focusDate=null,this.picker.hide().detach(),this._detachSecondaryEvents(),this.setViewMode(this.o.startView),this.o.forceParse&&this.inputField.val()&&this.setValue(),this._trigger("hide"),this)},destroy:function(){return this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date,this},paste:function(b){var c;if(b.originalEvent.clipboardData&&b.originalEvent.clipboardData.types&&-1!==a.inArray("text/plain",b.originalEvent.clipboardData.types))c=b.originalEvent.clipboardData.getData("text/plain");else{if(!window.clipboardData)return;c=window.clipboardData.getData("Text")}this.setDate(c),this.update(),b.preventDefault()},_utc_to_local:function(a){if(!a)return a;var b=new Date(a.getTime()+6e4*a.getTimezoneOffset());return b.getTimezoneOffset()!==a.getTimezoneOffset()&&(b=new Date(a.getTime()+6e4*b.getTimezoneOffset())),b},_local_to_utc:function(a){return a&&new Date(a.getTime()-6e4*a.getTimezoneOffset())},_zero_time:function(a){return a&&new Date(a.getFullYear(),a.getMonth(),a.getDate())},_zero_utc_time:function(a){return a&&c(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate())},getDates:function(){return a.map(this.dates,this._utc_to_local)},getUTCDates:function(){return a.map(this.dates,function(a){return new Date(a)})},getDate:function(){return this._utc_to_local(this.getUTCDate())},getUTCDate:function(){var a=this.dates.get(-1);return a!==b?new Date(a):null},clearDates:function(){this.inputField.val(""),this.update(),this._trigger("changeDate"),this.o.autoclose&&this.hide()},setDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.update.apply(this,b),this._trigger("changeDate"),this.setValue(),this},setUTCDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.setDates.apply(this,a.map(b,this._utc_to_local)),this},setDate:f("setDates"),setUTCDate:f("setUTCDates"),remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead"),setValue:function(){var a=this.getFormattedDate();return this.inputField.val(a),this},getFormattedDate:function(c){c===b&&(c=this.o.format);var d=this.o.language;return a.map(this.dates,function(a){return r.formatDate(a,c,d)}).join(this.o.multidateSeparator)},getStartDate:function(){return this.o.startDate},setStartDate:function(a){return this._process_options({startDate:a}),this.update(),this.updateNavArrows(),this},getEndDate:function(){return this.o.endDate},setEndDate:function(a){return this._process_options({endDate:a}),this.update(),this.updateNavArrows(),this},setDaysOfWeekDisabled:function(a){return this._process_options({daysOfWeekDisabled:a}),this.update(),this},setDaysOfWeekHighlighted:function(a){return this._process_options({daysOfWeekHighlighted:a}),this.update(),this},setDatesDisabled:function(a){return this._process_options({datesDisabled:a}),this.update(),this},place:function(){if(this.isInline)return this;var b=this.picker.outerWidth(),c=this.picker.outerHeight(),d=a(this.o.container),e=d.width(),f="body"===this.o.container?a(document).scrollTop():d.scrollTop(),g=d.offset(),h=[0];this.element.parents().each(function(){var b=a(this).css("z-index");"auto"!==b&&0!==Number(b)&&h.push(Number(b))});var i=Math.max.apply(Math,h)+this.o.zIndexOffset,j=this.component?this.component.parent().offset():this.element.offset(),k=this.component?this.component.outerHeight(!0):this.element.outerHeight(!1),l=this.component?this.component.outerWidth(!0):this.element.outerWidth(!1),m=j.left-g.left,n=j.top-g.top;"body"!==this.o.container&&(n+=f),this.picker.removeClass("datepicker-orient-top datepicker-orient-bottom datepicker-orient-right datepicker-orient-left"),"auto"!==this.o.orientation.x?(this.picker.addClass("datepicker-orient-"+this.o.orientation.x),"right"===this.o.orientation.x&&(m-=b-l)):j.left<0?(this.picker.addClass("datepicker-orient-left"),m-=j.left-10):m+b>e?(this.picker.addClass("datepicker-orient-right"),m+=l-b):this.o.rtl?this.picker.addClass("datepicker-orient-right"):this.picker.addClass("datepicker-orient-left");var o,p=this.o.orientation.y;if("auto"===p&&(o=-f+n-c,p=o<0?"bottom":"top"),this.picker.addClass("datepicker-orient-"+p),"top"===p?n-=c+parseInt(this.picker.css("padding-top")):n+=k,this.o.rtl){var q=e-(m+l);this.picker.css({top:n,right:q,zIndex:i})}else this.picker.css({top:n,left:m,zIndex:i});return this},_allow_update:!0,update:function(){if(!this._allow_update)return this;var b=this.dates.copy(),c=[],d=!1;return arguments.length?(a.each(arguments,a.proxy(function(a,b){b instanceof Date&&(b=this._local_to_utc(b)),c.push(b)},this)),d=!0):(c=this.isInput?this.element.val():this.element.data("date")||this.inputField.val(),c=c&&this.o.multidate?c.split(this.o.multidateSeparator):[c],delete this.element.data().date),c=a.map(c,a.proxy(function(a){return r.parseDate(a,this.o.format,this.o.language,this.o.assumeNearbyYear)},this)),c=a.grep(c,a.proxy(function(a){return!this.dateWithinRange(a)||!a},this),!0),this.dates.replace(c),this.o.updateViewDate&&(this.dates.length?this.viewDate=new Date(this.dates.get(-1)):this.viewDate<this.o.startDate?this.viewDate=new Date(this.o.startDate):this.viewDate>this.o.endDate?this.viewDate=new Date(this.o.endDate):this.viewDate=this.o.defaultViewDate),d?(this.setValue(),this.element.change()):this.dates.length&&String(b)!==String(this.dates)&&d&&(this._trigger("changeDate"),this.element.change()),!this.dates.length&&b.length&&(this._trigger("clearDate"),this.element.change()),this.fill(),this},fillDow:function(){if(this.o.showWeekDays){var b=this.o.weekStart,c="<tr>";for(this.o.calendarWeeks&&(c+='<th class="cw">&#160;</th>');b<this.o.weekStart+7;)c+='<th class="dow',-1!==a.inArray(b,this.o.daysOfWeekDisabled)&&(c+=" disabled"),c+='">'+q[this.o.language].daysMin[b++%7]+"</th>";c+="</tr>",this.picker.find(".datepicker-days thead").append(c)}},fillMonths:function(){for(var a,b=this._utc_to_local(this.viewDate),c="",d=0;d<12;d++)a=b&&b.getMonth()===d?" focused":"",c+='<span class="month'+a+'">'+q[this.o.language].monthsShort[d]+"</span>";this.picker.find(".datepicker-months td").html(c)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],f=this.viewDate.getUTCFullYear(),g=this.viewDate.getUTCMonth(),h=d();return b.getUTCFullYear()<f||b.getUTCFullYear()===f&&b.getUTCMonth()<g?c.push("old"):(b.getUTCFullYear()>f||b.getUTCFullYear()===f&&b.getUTCMonth()>g)&&c.push("new"),this.focusDate&&b.valueOf()===this.focusDate.valueOf()&&c.push("focused"),this.o.todayHighlight&&e(b,h)&&c.push("today"),-1!==this.dates.contains(b)&&c.push("active"),this.dateWithinRange(b)||c.push("disabled"),this.dateIsDisabled(b)&&c.push("disabled","disabled-date"),-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekHighlighted)&&c.push("highlighted"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!==a.inArray(b.valueOf(),this.range)&&c.push("selected"),b.valueOf()===this.range[0]&&c.push("range-start"),b.valueOf()===this.range[this.range.length-1]&&c.push("range-end")),c},_fill_yearsView:function(c,d,e,f,g,h,i){for(var j,k,l,m="",n=e/10,o=this.picker.find(c),p=Math.floor(f/e)*e,q=p+9*n,r=Math.floor(this.viewDate.getFullYear()/n)*n,s=a.map(this.dates,function(a){return Math.floor(a.getUTCFullYear()/n)*n}),t=p-n;t<=q+n;t+=n)j=[d],k=null,t===p-n?j.push("old"):t===q+n&&j.push("new"),-1!==a.inArray(t,s)&&j.push("active"),(t<g||t>h)&&j.push("disabled"),t===r&&j.push("focused"),i!==a.noop&&(l=i(new Date(t,0,1)),l===b?l={}:"boolean"==typeof l?l={enabled:l}:"string"==typeof l&&(l={classes:l}),!1===l.enabled&&j.push("disabled"),l.classes&&(j=j.concat(l.classes.split(/\s+/))),l.tooltip&&(k=l.tooltip)),m+='<sp
15733an class="'+j.join(" ")+'"'+(k?' title="'+k+'"':"")+">"+t+"</span>";o.find(".datepicker-switch").text(p+"-"+q),o.find("td").html(m)},fill:function(){var e,f,g=new Date(this.viewDate),h=g.getUTCFullYear(),i=g.getUTCMonth(),j=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,k=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,l=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,m=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,n=q[this.o.language].today||q.en.today||"",o=q[this.o.language].clear||q.en.clear||"",p=q[this.o.language].titleFormat||q.en.titleFormat,s=d(),t=(!0===this.o.todayBtn||"linked"===this.o.todayBtn)&&s>=this.o.startDate&&s<=this.o.endDate&&!this.weekOfDateIsDisabled(s);if(!isNaN(h)&&!isNaN(i)){this.picker.find(".datepicker-days .datepicker-switch").text(r.formatDate(g,p,this.o.language)),this.picker.find("tfoot .today").text(n).css("display",t?"table-cell":"none"),this.picker.find("tfoot .clear").text(o).css("display",!0===this.o.clearBtn?"table-cell":"none"),this.picker.find("thead .datepicker-title").text(this.o.title).css("display","string"==typeof this.o.title&&""!==this.o.title?"table-cell":"none"),this.updateNavArrows(),this.fillMonths();var u=c(h,i,0),v=u.getUTCDate();u.setUTCDate(v-(u.getUTCDay()-this.o.weekStart+7)%7);var w=new Date(u);u.getUTCFullYear()<100&&w.setUTCFullYear(u.getUTCFullYear()),w.setUTCDate(w.getUTCDate()+42),w=w.valueOf();for(var x,y,z=[];u.valueOf()<w;){if((x=u.getUTCDay())===this.o.weekStart&&(z.push("<tr>"),this.o.calendarWeeks)){var A=new Date(+u+(this.o.weekStart-x-7)%7*864e5),B=new Date(Number(A)+(11-A.getUTCDay())%7*864e5),C=new Date(Number(C=c(B.getUTCFullYear(),0,1))+(11-C.getUTCDay())%7*864e5),D=(B-C)/864e5/7+1;z.push('<td class="cw">'+D+"</td>")}y=this.getClassNames(u),y.push("day");var E=u.getUTCDate();this.o.beforeShowDay!==a.noop&&(f=this.o.beforeShowDay(this._utc_to_local(u)),f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),!1===f.enabled&&y.push("disabled"),f.classes&&(y=y.concat(f.classes.split(/\s+/))),f.tooltip&&(e=f.tooltip),f.content&&(E=f.content)),y=a.isFunction(a.uniqueSort)?a.uniqueSort(y):a.unique(y),z.push('<td class="'+y.join(" ")+'"'+(e?' title="'+e+'"':"")+' data-date="'+u.getTime().toString()+'">'+E+"</td>"),e=null,x===this.o.weekEnd&&z.push("</tr>"),u.setUTCDate(u.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").html(z.join(""));var F=q[this.o.language].monthsTitle||q.en.monthsTitle||"Months",G=this.picker.find(".datepicker-months").find(".datepicker-switch").text(this.o.maxViewMode<2?F:h).end().find("tbody span").removeClass("active");if(a.each(this.dates,function(a,b){b.getUTCFullYear()===h&&G.eq(b.getUTCMonth()).addClass("active")}),(h<j||h>l)&&G.addClass("disabled"),h===j&&G.slice(0,k).addClass("disabled"),h===l&&G.slice(m+1).addClass("disabled"),this.o.beforeShowMonth!==a.noop){var H=this;a.each(G,function(c,d){var e=new Date(h,c,1),f=H.o.beforeShowMonth(e);f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),!1!==f.enabled||a(d).hasClass("disabled")||a(d).addClass("disabled"),f.classes&&a(d).addClass(f.classes),f.tooltip&&a(d).prop("title",f.tooltip)})}this._fill_yearsView(".datepicker-years","year",10,h,j,l,this.o.beforeShowYear),this._fill_yearsView(".datepicker-decades","decade",100,h,j,l,this.o.beforeShowDecade),this._fill_yearsView(".datepicker-centuries","century",1e3,h,j,l,this.o.beforeShowCentury)}},updateNavArrows:function(){if(this._allow_update){var a,b,c=new Date(this.viewDate),d=c.getUTCFullYear(),e=c.getUTCMonth(),f=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,g=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,h=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,i=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,j=1;switch(this.viewMode){case 4:j*=10;case 3:j*=10;case 2:j*=10;case 1:a=Math.floor(d/j)*j<=f,b=Math.floor(d/j)*j+j>h;break;case 0:a=d<=f&&e<=g,b=d>=h&&e>=i}this.picker.find(".prev").toggleClass("disabled",a),this.picker.find(".next").toggleClass("disabled",b)}},click:function(b){b.preventDefault(),b.stopPropagation();var e,f,g,h;e=a(b.target),e.hasClass("datepicker-switch")&&this.viewMode!==this.o.maxViewMode&&this.setViewMode(this.viewMode+1),e.hasClass("today")&&!e.hasClass("day")&&(this.setViewMode(0),this._setDate(d(),"linked"===this.o.todayBtn?null:"view")),e.hasClass("clear")&&this.clearDates(),e.hasClass("disabled")||(e.hasClass("month")||e.hasClass("year")||e.hasClass("decade")||e.hasClass("century"))&&(this.viewDate.setUTCDate(1),f=1,1===this.viewMode?(h=e.parent().find("span").index(e),g=this.viewDate.getUTCFullYear(),this.viewDate.setUTCMonth(h)):(h=0,g=Number(e.text()),this.viewDate.setUTCFullYear(g)),this._trigger(r.viewModes[this.viewMode-1].e,this.viewDate),this.viewMode===this.o.minViewMode?this._setDate(c(g,h,f)):(this.setViewMode(this.viewMode-1),this.fill())),this.picker.is(":visible")&&this._focused_from&&this._focused_from.focus(),delete this._focused_from},dayCellClick:function(b){var c=a(b.currentTarget),d=c.data("date"),e=new Date(d);this.o.updateViewDate&&(e.getUTCFullYear()!==this.viewDate.getUTCFullYear()&&this._trigger("changeYear",this.viewDate),e.getUTCMonth()!==this.viewDate.getUTCMonth()&&this._trigger("changeMonth",this.viewDate)),this._setDate(e)},navArrowsClick:function(b){var c=a(b.currentTarget),d=c.hasClass("prev")?-1:1;0!==this.viewMode&&(d*=12*r.viewModes[this.viewMode].navStep),this.viewDate=this.moveMonth(this.viewDate,d),this._trigger(r.viewModes[this.viewMode].e,this.viewDate),this.fill()},_toggle_multidate:function(a){var b=this.dates.contains(a);if(a||this.dates.clear(),-1!==b?(!0===this.o.multidate||this.o.multidate>1||this.o.toggleActive)&&this.dates.remove(b):!1===this.o.multidate?(this.dates.clear(),this.dates.push(a)):this.dates.push(a),"number"==typeof this.o.multidate)for(;this.dates.length>this.o.multidate;)this.dates.remove(0)}
vendor: 6,432 bytes, line 15733
15733,_setDate:function(a,b){b&&"date"!==b||this._toggle_multidate(a&&new Date(a)),(!b&&this.o.updateViewDate||"view"===b)&&(this.viewDate=a&&new Date(a)),this.fill(),this.setValue(),b&&"view"===b||this._trigger("changeDate"),this.inputField.trigger("change"),!this.o.autoclose||b&&"date"!==b||this.hide()},moveDay:function(a,b){var c=new Date(a);return c.setUTCDate(a.getUTCDate()+b),c},moveWeek:function(a,b){return this.moveDay(a,7*b)},moveMonth:function(a,b){if(!g(a))return this.o.defaultViewDate;if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),h=e.getUTCMonth(),i=Math.abs(b);if(b=b>0?1:-1,1===i)d=-1===b?function(){return e.getUTCMonth()===h}:function(){return e.getUTCMonth()!==c},c=h+b,e.setUTCMonth(c),c=(c+12)%12;else{for(var j=0;j<i;j++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!==e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},moveAvailableDate:function(a,b,c){do{if(a=this[c](a,b),!this.dateWithinRange(a))return!1;c="moveDay"}while(this.dateIsDisabled(a));return a},weekOfDateIsDisabled:function(b){return-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled)},dateIsDisabled:function(b){return this.weekOfDateIsDisabled(b)||a.grep(this.o.datesDisabled,function(a){return e(b,a)}).length>0},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(!this.picker.is(":visible"))return void(40!==a.keyCode&&27!==a.keyCode||(this.show(),a.stopPropagation()));var b,c,d=!1,e=this.focusDate||this.viewDate;switch(a.keyCode){case 27:this.focusDate?(this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill()):this.hide(),a.preventDefault(),a.stopPropagation();break;case 37:case 38:case 39:case 40:if(!this.o.keyboardNavigation||7===this.o.daysOfWeekDisabled.length)break;b=37===a.keyCode||38===a.keyCode?-1:1,0===this.viewMode?a.ctrlKey?(c=this.moveAvailableDate(e,b,"moveYear"))&&this._trigger("changeYear",this.viewDate):a.shiftKey?(c=this.moveAvailableDate(e,b,"moveMonth"))&&this._trigger("changeMonth",this.viewDate):37===a.keyCode||39===a.keyCode?c=this.moveAvailableDate(e,b,"moveDay"):this.weekOfDateIsDisabled(e)||(c=this.moveAvailableDate(e,b,"moveWeek")):1===this.viewMode?(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveMonth")):2===this.viewMode&&(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveYear")),c&&(this.focusDate=this.viewDate=c,this.setValue(),this.fill(),a.preventDefault());break;case 13:if(!this.o.forceParse)break;e=this.focusDate||this.dates.get(-1)||this.viewDate,this.o.keyboardNavigation&&(this._toggle_multidate(e),d=!0),this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.setValue(),this.fill(),this.picker.is(":visible")&&(a.preventDefault(),a.stopPropagation(),this.o.autoclose&&this.hide());break;case 9:this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill(),this.hide()}d&&(this.dates.length?this._trigger("changeDate"):this._trigger("clearDate"),this.inputField.trigger("change"))},setViewMode:function(a){this.viewMode=a,this.picker.children("div").hide().filter(".datepicker-"+r.viewModes[this.viewMode].clsName).show(),this.updateNavArrows(),this._trigger("changeViewMode",new Date(this.viewDate))}};var l=function(b,c){a.data(b,"datepicker",this),this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,this.keepEmptyValues=c.keepEmptyValues,delete c.keepEmptyValues,n.call(a(this.inputs),c).on("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a.data(b,"datepicker")}),this.updateDates()};l.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.getUTCDate()}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},clearDates:function(){a.each(this.pickers,function(a,b){b.clearDates()})},dateUpdated:function(c){if(!this.updating){this.updating=!0;var d=a.data(c.target,"datepicker");if(d!==b){var e=d.getUTCDate(),f=this.keepEmptyValues,g=a.inArray(c.target,this.inputs),h=g-1,i=g+1,j=this.inputs.length;if(-1!==g){if(a.each(this.pickers,function(a,b){b.getUTCDate()||b!==d&&f||b.setUTCDate(e)}),e<this.dates[h])for(;h>=0&&e<this.dates[h];)this.pickers[h--].setUTCDate(e);else if(e>this.dates[i])for(;i<j&&e>this.dates[i];)this.pickers[i++].setUTCDate(e);this.updateDates(),delete this.updating}}}},destroy:function(){a.map(this.pickers,function(a){a.destroy()}),a(this.inputs).off("changeDate",this.dateUpdated),delete this.element.data().datepicker},remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead")};var m=a.fn.datepicker,n=function(c){var d=Array.apply(null,arguments);d.shift();var e;if(this.each(function(){var b=a(this),f=b.data("datepicker"),g="object"==typeof c&&c;if(!f){var j=h(this,"date"),m=a.extend({},o,j,g),n=i(m.language),p=a.extend({},o,n,j,g);b.hasClass("input-daterange")||p.inputs?(a.extend(p,{inputs:p.inputs||b.find("input").toArray()}),f=new l(this,p)):f=new k(this,p),b.data("datepicker",f)}"string"==typeof c&&"function"==typeof f[c]&&(e=f[c].apply(f,d))}),e===b||e instanceof k||e instanceof l)return this;if(this.length>1)throw new Error("Using only allowed for the collection of a single element ("+c+" function)");return e};a.fn.datepicker=n;var o=a.fn.datepicker.defaults={assumeNearbyYear:!1,autoclose:!1,beforeShowDay:a.noop,beforeShowMonth:a.noop,beforeShowYear:a.noop,beforeShowDecade:a.noop,beforeShowCentury:a.noop,calendarWeeks:!1,clearBtn:!1,toggleActive:!1,daysOfWeekDisabled:[],daysOfWeekHighlighted:[],datesDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keepEmptyValues:!1,keyboardNavigation:!0,language:"en",minViewMode:0,maxViewMode:4,multidate:!1,multidateSeparator:",",orientation:"auto",rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,updateViewDate:!0,weekStart:0,disableTouchKeyboard:!1,enableOnReadonly:!0,showOnFocus:!0,zIndexOffset:10,container:"body",immediateUpdates:!1,title:"",templates:{leftArrow:"&#x00AB;",rightArrow:"&#x00BB;"},showWeekDays:!0},p=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=k;var q=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
15733ay","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM yyyy"}},r={viewModes:[{names:["days","month"],clsName:"days",e:"changeMonth"},{names:["months","year"],clsName:"months",e:"changeYear",navStep:1},{names:["years","decade"],clsName:"years",e:"changeDecade",navStep:10},{names:["decades","century"],clsName:"decades",e:"changeCentury",navStep:100},{names:["centuries","millennium"],clsName:"centuries",e:"changeMillennium",navStep:1e3}],validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,parseFormat:function(a){if("function"==typeof a.toValue&&"function"==typeof a.toDisplay)return a;var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,e,f,g){function h(a,b){return!0===b&&(b=10),a<100&&(a+=2e3)>(new Date).getFullYear()+b&&(a-=100),a}function i(){var a=this.slice(0,j[n].length),b=j[n].slice(0,a.length);return a.toLowerCase()===b.toLowerCase()}if(!c)return b;if(c instanceof Date)return c;if("string"==typeof e&&(e=r.parseFormat(e)),e.toValue)return e.toValue(c,e,f);var j,l,m,n,o,p={d:"moveDay",m:"moveMonth",w:"moveWeek",y:"moveYear"},s={yesterday:"-1d",today:"+0d",tomorrow:"+1d"};if(c in s&&(c=s[c]),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(c)){for(j=c.match(/([\-+]\d+)([dmwy])/gi),c=new Date,n=0;n<j.length;n++)l=j[n].match(/([\-+]\d+)([dmwy])/i),m=Number(l[1]),o=p[l[2].toLowerCase()],c=k.prototype[o](c,m);return k.prototype._zero_utc_time(c)}j=c&&c.match(this.nonpunctuation)||[];var t,u,v={},w=["yyyy","yy","M","MM","m","mm","d","dd"],x={yyyy:function(a,b){return a.setUTCFullYear(g?h(b,g):b)},m:function(a,b){if(isNaN(a))return a;for(b-=1;b<0;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!==b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};x.yy=x.yyyy,x.M=x.MM=x.mm=x.m,x.dd=x.d,c=d();var y=e.parts.slice();if(j.length!==y.length&&(y=a(y).filter(function(b,c){return-1!==a.inArray(c,w)}).toArray()),j.length===y.length){var z;for(n=0,z=y.length;n<z;n++){if(t=parseInt(j[n],10),l=y[n],isNaN(t))switch(l){case"MM":u=a(q[f].months).filter(i),t=a.inArray(u[0],q[f].months)+1;break;case"M":u=a(q[f].monthsShort).filter(i),t=a.inArray(u[0],q[f].monthsShort)+1}v[l]=t}var A,B;for(n=0;n<w.length;n++)(B=w[n])in v&&!isNaN(v[B])&&(A=new Date(c),x[B](A,v[B]),isNaN(A)||(c=A))}return c},formatDate:function(b,c,d){if(!b)return"";if("string"==typeof c&&(c=r.parseFormat(c)),c.toDisplay)return c.toDisplay(b,c,d);var e={d:b.getUTCDate(),D:q[d].daysShort[b.getUTCDay()],DD:q[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:q[d].monthsShort[b.getUTCMonth()],MM:q[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m,b=[];for(var f=a.extend([],c.separators),g=0,h=c.parts.length;g<=h;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},
15734headTemplate:'<thead><tr><th colspan="7" class="datepicker-title"></th></tr><tr><th class="prev">'+o.templates.leftArrow+'</th><th colspan="5" class="datepicker-switch"></th><th class="next">'+o.templates.rightArrow+"</th></tr></thead>",contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};r.template='<div class="datepicker"><div class="datepicker-days"><table class="table-condensed">'+r.headTemplate+"<tbody></tbody>"+r.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-decades"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-centuries"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+"</table></div></div>",a.fn.datepicker.DPGlobal=r,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=m,this},a.fn.datepicker.version="1.9.0",a.fn.datepicker.deprecated=function(a){var b=window.console;b&&b.warn&&b.warn("DEPRECATED: "+a)},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),n.call(c,"show"))}),a(function(){n.call(a('[data-provide="datepicker-inline"]'))})});
15735"use strict";
15736$.fn.datepicker.defaults.zIndexOffset = 10;
15737(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(d,f){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===f){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function a(){var q,k,p,l,j,n,m,o;k=(new Date()).toString();p=((m=k.split("(")[1])!=null?m.slice(0,-1):0)||k.split(" ");if(p instanceof Array){n=[];for(var l=0,j=p.length;l<j;l++){o=p[l];if((q=(m=o.match(/\b[A-Z]+\b/))!==null)?m[0]:0){n.push(q)}}p=n.pop()}return p}function h(){return new Date(Date.UTC.apply(Date,arguments))}var g=function(k,j){var m=this;this.element=d(k);this.container=j.container||"body";this.language=j.language||this.element.data("date-language")||"en";this.language=this.language in e?this.language:this.language.split("-")[0];this.language=this.language in e?this.language:"en";this.isRTL=e[this.language].rtl||false;this.formatType=j.formatType||this.element.data("format-type")||"standard";this.format=c.parseFormat(j.format||this.element.data("date-format")||e[this.language].format||c.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=j.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=j.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=j.linkField||this.element.data("link-field")||false;this.linkFormat=c.parseFormat(j.linkFormat||this.element.data("link-format")||c.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=j.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=j.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=j.showMeridian||this.element.data("show-meridian")||false;this.initialDate=j.initialDate||new Date();this.zIndex=j.zIndex||this.element.data("z-index")||f;this.title=typeof j.title==="undefined"?false:j.title;this.timezone=j.timezone||a();this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(n){if(d(n.target).closest(".datetimepicker").length===0){m.hide()}};this.formatViewType="datetime";if("formatViewType" in j){this.formatViewType=j.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in j){this.minView=j.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=c.convertViewMode(this.minView);this.maxView=c.modes.length-1;if("maxView" in j){this.maxView=j.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=c.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in j){this.wheelViewModeNavigation=j.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in j){this.wheelViewModeNavigationInverseDirection=j.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in j){this.wheelViewModeNavigationDelay=j.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in j){this.startViewMode=j.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=c.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in j){this.viewSelect=j.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=c.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in j){this.forceParse=j.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var l=this.bootcssVer===3?c.templateV3:c.template;while(l.indexOf("{iconType}")!==-1){l=l.replace("{iconType}",this.icontype)}while(l.indexOf("{leftArrow}")!==-1){l=l.replace("{leftArrow}",this.icons.leftArrow)}while(l.indexOf("{rightArrow}")!==-1){l=l.replace("{rightArrow}",this.icons.rightArrow)}this.picker=d(l).appendTo(this.isInline?this.element:this.container).on({click:d.proxy(this.click,this),mousedown:d.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(d.fn.mousewheel){this.picker.on({mousewheel:d.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var i=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(i).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}d(document).on("mousedown touchend",this.clickedOutside);this.autoclose=false;if("autoclose" in j){this.autoclose=j.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in j){this.keyboardNavigation=j.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(j.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(j.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(j.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=0;if(typeof j.weekStart!=="undefined"){this.weekStart=j.weekStart}else{if(typeof this.element.data("date-weekstart")!=="undefined"){this.weekStart=this.element.data("date-weekstart")}else{if(typeof e[this.language].weekStart!=="undefined"){this.weekStart=e[this.language].weekStart}}}this.weekStart=this.weekStart%7;this.weekEnd=((this.weekStart+6)%7);this.onRenderDay=function(n){var p=(j.onRenderDay||function(){return[]})(n);if(typeof p==="string"){p=[p]}var o=["day"];return o.concat((p?p:[]))};this.onRenderHour=function(n){var p=(j.onRenderHour||function(){return[]})(n);var o=["hour"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.onRenderMinute=function(n){var p=(j.onRenderMinute||function(){return[]})(n);var o=["minute"];if(typeof p==="string"){p=[p]}if(n<this.startDate||n>this.endDate){o.push("disabled")}else{if(Math.floor(this.date.getUTCMinutes()/this.minuteStep)===Math.floor(n.getUTCMinutes()/this.minuteStep)){o.push("active")}}return o.concat((p?p:[]))};this.onRenderYear=function(o){var q=(j.onRenderYear||function(){return[]})(o);var p=["year"];if(typeof q==="string"){q=[q]}if(this.date.getUTCFullYear()===o.getUTCFullYear()){p.push("active")}var n=o.getUTCFullYear();var r=this.endDate.getUTCFullYear();if(o<this.startDate||n>r){p.push("disabled")}return p.concat((q?q:[]))};this.onRenderMonth=function(n){var p=(j.onRenderMonth||function(){return[]})(n);var o=["month"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.startDate=new Date(-8639968443048000);this.endDate=new Date(8639968443048000);this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(j.startDate||this.element.data("date-startdate"));this.setEndDate(j.endDate||this.element.data("date-enddate"));this.setDatesDisabled(j.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(j.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(j.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(j.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};g.prototype={constructor:g,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}],[this.component,{click:d.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:d.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:d.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(i){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();d(window).on("resize",d.proxy(this.place,this));if(i){i.stopPropagation();i.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();d(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){d(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();d(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var i=this.getUTCDate();if(i===null){return null}return new Date(i.getTime()+(i.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},getInitialDate:function(){return this.initialDate},setInitialDate:function(i){this.initialDate=i},setDate:function(i){this.setUTCDate(new Date(i.getTime()-(i.getTimezoneOffset()*60000)))},setUTCDate:function(i){if(i>=this.startDate&&i<=this.endDate){this.date=i;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:i,startDate:this.startDate,endD
15737ate:this.endDate})}},setFormat:function(j){this.format=c.parseFormat(j,this.formatType);var i;if(this.isInput){i=this.element}else{if(this.component){i=this.element.find("input")}}if(i&&i.val()){this.setValue()}},setValue:function(){var i=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(i)}this.element.data("date",i)}else{this.element.val(i)}if(this.linkField){d("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(i){i=i||this.format;return c.formatDate(this.date,i,this.language,this.formatType,this.timezone)},setStartDate:function(i){this.startDate=i||this.startDate;if(this.startDate.valueOf()!==8639968443048000){this.startDate=c.parseDate(this.startDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setEndDate:function(i){this.endDate=i||this.endDate;if(this.endDate.valueOf()!==8639968443048000){this.endDate=c.parseDate(this.endDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!d.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}var i=this;this.datesDisabled=d.map(this.datesDisabled,function(k){return c.parseDate(k,i.format,i.language,i.formatType,i.timezone).toDateString()});this.update();this.updateNavArrows()},setTitle:function(i,j){return this.picker.find(i).find("th:eq(1)").text(this.title===false?j:this.title)},setDaysOfWeekDisabled:function(i){this.daysOfWeekDisabled=i||[];if(!d.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=d.map(this.daysOfWeekDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(i){this.minutesDisabled=i||[];if(!d.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=d.map(this.minutesDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(i){this.hoursDisabled=i||[];if(!d.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=d.map(this.hoursDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var j=0;d("div").each(function(){var o=parseInt(d(this).css("zIndex"),10);if(o>j){j=o}});this.zIndex=j+10}var n,m,l,k;if(this.container instanceof d){k=this.container.offset()}else{k=d(this.container).offset()}if(this.component){n=this.component.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.component.outerWidth()-this.picker.outerWidth()}}else{n=this.element.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.element.outerWidth()-this.picker.outerWidth()}}var i=document.body.clientWidth||window.innerWidth;if(l+220>i){l=i-220}if(this.pickerPosition==="top-left"||this.pickerPosition==="top-right"){m=n.top-this.picker.outerHeight()}else{m=n.top+this.height}m=m-k.top;l=l-k.left;this.picker.css({top:m,left:l,zIndex:this.zIndex})},hour_minute:"^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",update:function(){var i,j=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){i=arguments[0];j=true}else{i=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof i==="string"){i=i.replace(/^\s+|\s+$/g,"")}}if(!i){i=new Date();j=false}if(typeof i==="string"){if(new RegExp(this.hour_minute).test(i)||new RegExp(this.hour_minute+":[0-5][0-9]").test(i)){i=this.getDate()}}this.date=c.parseDate(i,this.format,this.language,this.formatType,this.timezone);if(j){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var i=this.weekStart,j="<tr>";while(i<this.weekStart+7){j+='<th class="dow">'+e[this.language].daysMin[(i++)%7]+"</th>"}j+="</tr>";this.picker.find(".datetimepicker-days thead").append(j)},fillMonths:function(){var l="";var m=new Date(this.viewDate);for(var k=0;k<12;k++){m.setUTCMonth(k);var j=this.onRenderMonth(m);l+='<span class="'+j.join(" ")+'">'+e[this.language].monthsShort[k]+"</span>"}this.picker.find(".datetimepicker-months td").html(l)},fill:function(){if(!this.date||!this.viewDate){return}var E=new Date(this.viewDate),t=E.getUTCFullYear(),G=E.getUTCMonth(),n=E.getUTCDate(),A=E.getUTCHours(),w=this.startDate.getUTCFullYear(),B=this.startDate.getUTCMonth(),p=this.endDate.getUTCFullYear(),x=this.endDate.getUTCMonth()+1,q=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),D=new Date();this.setTitle(".datetimepicker-days",e[this.language].months[G]+" "+t);if(this.formatViewType==="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+e[this.language].months[G]+" "+t);this.setTitle(".datetimepicker-minutes",n+" "+e[this.language].months[G]+" "+t)}this.picker.find("tfoot th.today").text(e[this.language].today||e.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(e[this.language].clear||e.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var I=h(t,G-1,28,0,0,0,0),z=c.getDaysInMonth(I.getUTCFullYear(),I.getUTCMonth());I.setUTCDate(z);I.setUTCDate(z-(I.getUTCDay()-this.weekStart+7)%7);var j=new Date(I);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var r=[];var F;
15737while(I.valueOf()<j){if(I.getUTCDay()===this.weekStart){r.push("<tr>")}F=this.onRenderDay(I);if(I.getUTCFullYear()<t||(I.getUTCFullYear()===t&&I.getUTCMonth()<G)){F.push("old")}else{if(I.getUTCFullYear()>t||(I.getUTCFullYear()===t&&I.getUTCMonth()>G)){F.push("new")}}if(this.todayHighlight&&I.getUTCFullYear()===D.getFullYear()&&I.getUTCMonth()===D.getMonth()&&I.getUTCDate()===D.getDate()){F.push("today")}if(I.valueOf()===q){F.push("active")}if((I.valueOf()+86400000)<=this.startDate||I.valueOf()>this.endDate||d.inArray(I.getUTCDay(),this.daysOfWeekDisabled)!==-1||d.inArray(I.toDateString(),this.datesDisabled)!==-1){F.push("disabled")}r.push('<td class="'+F.join(" ")+'">'+I.getUTCDate()+"</td>");if(I.getUTCDay()===this.weekEnd){r.push("</tr>")}I.setUTCDate(I.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(r.join(""));r=[];var u="",C="",s="";var l=this.hoursDisabled||[];E=new Date(this.viewDate);for(var y=0;y<24;y++){E.setUTCHours(y);F=this.onRenderHour(E);if(l.indexOf(y)!==-1){F.push("disabled")}var v=h(t,G,n,y);if((v.valueOf()+3600000)<=this.startDate||v.valueOf()>this.endDate){F.push("disabled")}else{if(A===y){F.push("active")}}if(this.showMeridian&&e[this.language].meridiem.length===2){C=(y<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="hour"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(y%12?y%12:12);if(y<12){F.push("hour_am")}else{F.push("hour_pm")}r.push('<span class="'+F.join(" ")+'">'+u+"</span>");if(y===23){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+u+"</span>")}}this.picker.find(".datetimepicker-hours td").html(r.join(""));r=[];u="";C="";s="";var m=this.minutesDisabled||[];E=new Date(this.viewDate);for(var y=0;y<60;y+=this.minuteStep){if(m.indexOf(y)!==-1){continue}E.setUTCMinutes(y);E.setUTCSeconds(0);F=this.onRenderMinute(E);if(this.showMeridian&&e[this.language].meridiem.length===2){C=(A<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="minute"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(A%12?A%12:12);r.push('<span class="'+F.join(" ")+'">'+u+":"+(y<10?"0"+y:y)+"</span>");if(y===59){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+A+":"+(y<10?"0"+y:y)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(r.join(""));var J=this.date.getUTCFullYear();var o=this.setTitle(".datetimepicker-months",t).end().find(".month").removeClass("active");if(J===t){o.eq(this.date.getUTCMonth()).addClass("active")}if(t<w||t>p){o.addClass("disabled")}if(t===w){o.slice(0,B).addClass("disabled")}if(t===p){o.slice(x).addClass("disabled")}r="";t=parseInt(t/10,10)*10;var H=this.setTitle(".datetimepicker-years",t+"-"+(t+9)).end().find("td");t-=1;E=new Date(this.viewDate);for(var y=-1;y<11;y++){E.setUTCFullYear(t);F=this.onRenderYear(E);if(y===-1||y===10){F.push(b)}r+='<span class="'+F.join(" ")+'">'+t+"</span>";t+=1}H.html(r);this.place()},updateNavArrows:function(){var m=new Date(this.viewDate),k=m.getUTCFullYear(),l=m.getUTCMonth(),j=m.getUTCDate(),i=m.getUTCHours();switch(this.viewMode){case 0:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()&&i<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()&&i>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(k<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(j){j.preventDefault();j.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var i=j.originalEvent;var l=i.wheelDelta;var k=l>0?1:(l===0)?0:-1;
15737if(this.wheelViewModeNavigationInverseDirection){k=-k}this.showMode(k);setTimeout(d.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(m){m.stopPropagation();m.preventDefault();var n=d(m.target).closest("span, td, th, legend");if(n.is("."+this.icontype)){n=d(n).parent().closest("span, td, th, legend")}if(n.length===1){if(n.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(n[0].nodeName.toLowerCase()){case"th":switch(n[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=c.modes[this.viewMode].navStep*(n[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,i);break;case 1:this.viewDate=this.moveDate(this.viewDate,i);break;case 2:this.viewDate=this.moveMonth(this.viewDate,i);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,i);break}this.fill();this.element.trigger({type:n[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var j=new Date();j=h(j.getFullYear(),j.getMonth(),j.getDate(),j.getHours(),j.getMinutes(),j.getSeconds(),0);if(j<this.startDate){j=this.startDate}else{if(j>this.endDate){j=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(j);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!n.is(".disabled")){var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),q=this.viewDate.getUTCDate(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".month")){this.viewDate.setUTCDate(1);o=n.parent().find("span").index(n);q=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(o);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".year")){this.viewDate.setUTCDate(1);p=parseInt(n.text(),10)||0;this.viewDate.setUTCFullYear(p);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".hour")){r=parseInt(n.text(),10)||0;if(n.hasClass("hour_am")||n.hasClass("hour_pm")){if(r===12&&n.hasClass("hour_am")){r=0}else{if(r!==12&&n.hasClass("hour_pm")){r+=12}}}this.viewDate.setUTCHours(r);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".minute")){k=parseInt(n.text().substr(n.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(k);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(p,o,q,r,k,s,0))}}}}}if(this.viewMode!==0){var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(n.is(".day")&&!n.is(".disabled")){var q=parseInt(n.text(),10)||1;var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".old")){if(o===0){o=11;p-=1}else{o-=1}}else{if(n.is(".new")){if(o===11){o=0;p+=1}else{o+=1}}}this.viewDate.setUTCFullYear(p);this.viewDate.setUTCMonth(o,q);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(p,o,q,r,k,s,0))}}var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(i,k){if(!k||k==="date"){this.date=i}if(!k||k==="view"){this.viewDate=i}this.fill();this.setValue();var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j){j.change()}this.element.trigger({type:"changeDate",date:this.getDate()});if(i===null){this.date=this.viewDate}},moveMinute:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCMinutes(k.getUTCMinutes()+(i*this.minuteStep));return k},moveHour:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCHours(k.getUTCHours()+i);return k}
15737,moveDate:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCDate(k.getUTCDate()+i);return k},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m===1){p=k===-1?function(){return n.getUTCMonth()===o}:function(){return n.getUTCMonth()!==q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!==n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(j,i){return this.moveMonth(j,i*12)},dateWithinRange:function(i){return i>=this.startDate&&i<=this.endDate},keydown:function(o){if(this.picker.is(":not(:visible)")){if(o.keyCode===27){this.show()}return}var k=false,j,i,n;switch(o.keyCode){case 27:this.hide();o.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}j=o.keyCode===37?-1:1;var m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j);n=this.moveDate(this.viewDate,j)}else{if(m===1){i=this.moveHour(this.date,j);n=this.moveHour(this.viewDate,j)}else{if(m===0){i=this.moveMinute(this.date,j);n=this.moveMinute(this.viewDate,j)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 38:case 40:if(!this.keyboardNavigation){break}j=o.keyCode===38?-1:1;m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j*7);n=this.moveDate(this.viewDate,j*7)}else{if(m===1){if(this.showMeridian){i=this.moveHour(this.date,j*6);n=this.moveHour(this.viewDate,j*6)}else{i=this.moveHour(this.date,j*4);n=this.moveHour(this.viewDate,j*4)}}else{if(m===0){i=this.moveMinute(this.date,j*4);n=this.moveMinute(this.viewDate,j*4)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 13:if(this.viewMode!==0){var p=this.viewMode;this.showMode(-1);this.fill();if(p===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}o.preventDefault();break;case 9:this.hide();break}if(k){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(i){if(i){var j=Math.max(0,Math.min(c.modes.length-1,this.viewMode+i));if(j>=this.minView&&j<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:j});this.viewMode=j}}this.picker.find(">div").hide().filter(".datetimepicker-"+c.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(){this._setDate(null,"date")},convertViewModeText:function(i){switch(i){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=d.fn.datetimepicker;d.fn.datetimepicker=function(k){var i=Array.apply(null,arguments);i.shift();var j;this.each(function(){var n=d(this),m=n.data("datetimepicker"),l=typeof k==="object"&&k;if(!m){n.data("datetimepicker",(m=new g(this,d.extend({},d.fn.datetimepicker.defaults,l))))}if(typeof k==="string"&&typeof m[k]==="function"){j=m[k].apply(m,i);if(j!==f){return false}}});if(j!==f){return j}else{return this}};d.fn.datetimepicker.defaults={};d.fn.datetimepicker.Constructor=g;var e=d.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var c={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(i){return(((i%4===0)&&(i%100!==0))||(i%400===0))},getDaysInMonth:function(i,j){return[31,(c.isLeapYear(i)?29:28),31,30,31,30,31,31,30,31,30,31][j]},getDefaultFormat:function(i,j){if(i==="standard"){if(j==="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(i==="php"){if(j==="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(i){if(i==="standard"){return/t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(i==="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(l,j){var i=l.replace(this.validParts(j),"\0").split("\0"),k=l.match(this.validParts(j));if(!i||!i.length||!k||k.length===0){throw new Error("Invalid date format.")}return{separators:i,parts:k}},parseDate:function(A,y,v,j,r){if(A instanceof Date){var u=new Date(A.valueOf()-A.getTimezoneOffset()*60000);u.setMilliseconds(0);return u}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii:ss",j)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(A)){var l=/([-+]\d+)([dmwy])/,q=A.match(/([-+]\d+)([dmwy])/g),t,p;A=new Date();for(var x=0;x<q.length;x++){t=l.exec(q[x]);p=parseInt(t[1]);switch(t[2]){case"d":A.setUTCDate(A.getUTCDate()+p);break;case"m":A=g.prototype.moveMonth.call(g.prototype,A,p);break;case"w":A.setUTCDate(A.getUTCDate()+p*7);break;case"y":A=g.prototype.moveYear.call(g.prototype,A,p);break}}return h(A.getUTCFullYear(),A.getUTCMonth(),A.getUTCDate(),A.getUTCHours(),A.getUTCMinutes(),A.getUTCSeconds(),0)}var q=A&&A.toString().match(this.nonpunctuation)||[],A=new Date(0,0,0,0,0,0,0),m={},z=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P","z","Z"],o={hh:function(s,i){return s.setUTCHours(i)},h:function(s,i){return s.setUTCHours(i)},HH:function(s,i){return s.setUTCHours(i===12?0:i)},H:function(s,i){return s.setUTCHours(i===12?0:i)},ii:function(s,i){return s.setUTCMinutes(i)},i:function(s,i){return s.setUTCMinutes(i)},ss:function(s,i){return s.setUTCSeconds(i)},s:function(s,i){return s.setUTCSeconds(i)},yyyy:function(s,i){return s.setUTCFullYear(i)},yy:function(s,i){return s.setUTCFullYear(2000+i)},m:function(s,i){i-=1;while(i<0){i+=12}i%=12;s.setUTCMonth(i);while(s.getUTCMonth()!==i){if(isNaN(s.getUTCMonth())){return s}else{s.setUTCDate(s.getUTCDate()-1)}}return s},d:function(s,i){return s.setUTCDate(i)},p:function(s,i){return s.setUTCHours(i===1?s.getUTCHours()+12:s.getUTCHours())},z:function(){return r}},B,k,t;o.M=o.MM=o.mm=o.m;o.dd=o.d;o.P=o.p;o.Z=o.z;A=h(A.getFullYear(),A.getMonth(),A.getDate(),A.getHours(),A.getMinutes(),A.getSeconds());if(q.length===y.parts.length){for(var x=0,w=y.parts.length;x<w;x++){B=parseInt(q[x],10);
15737t=y.parts[x];if(isNaN(B)){switch(t){case"MM":k=d(e[v].months).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i===s});B=d.inArray(k[0],e[v].months)+1;break;case"M":k=d(e[v].monthsShort).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i.toLowerCase()===s.toLowerCase()});B=d.inArray(k[0],e[v].monthsShort)+1;break;case"p":case"P":B=d.inArray(q[x].toLowerCase(),e[v].meridiem);break;case"z":case"Z":r;break}}m[t]=B}for(var x=0,n;x<z.length;x++){n=z[x];if(n in m&&!isNaN(m[n])){o[n](A,m[n])}}}return A},formatDate:function(l,q,m,p,o){if(l===null){return""}var k;if(p==="standard"){k={t:l.getTime(),yy:l.getUTCFullYear().toString().substring(2),yyyy:l.getUTCFullYear(),m:l.getUTCMonth()+1,M:e[m].monthsShort[l.getUTCMonth()],MM:e[m].months[l.getUTCMonth()],d:l.getUTCDate(),D:e[m].daysShort[l.getUTCDay()],DD:e[m].days[l.getUTCDay()],p:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),h:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds(),z:o};if(e[m].meridiem.length===2){k.H=(k.h%12===0?12:k.h%12)}else{k.H=k.h}k.HH=(k.H<10?"0":"")+k.H;k.P=k.p.toUpperCase();k.Z=k.z;k.hh=(k.h<10?"0":"")+k.h;k.ii=(k.i<10?"0":"")+k.i;k.ss=(k.s<10?"0":"")+k.s;k.dd=(k.d<10?"0":"")+k.d;k.mm=(k.m<10?"0":"")+k.m}else{if(p==="php"){k={y:l.getUTCFullYear().toString().substring(2),Y:l.getUTCFullYear(),F:e[m].months[l.getUTCMonth()],M:e[m].monthsShort[l.getUTCMonth()],n:l.getUTCMonth()+1,t:c.getDaysInMonth(l.getUTCFullYear(),l.getUTCMonth()),j:l.getUTCDate(),l:e[m].days[l.getUTCDay()],D:e[m].daysShort[l.getUTCDay()],w:l.getUTCDay(),N:(l.getUTCDay()===0?7:l.getUTCDay()),S:(l.getUTCDate()%10<=e[m].suffix.length?e[m].suffix[l.getUTCDate()%10-1]:""),a:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),g:(l.getUTCHours()%12===0?12:l.getUTCHours()%12),G:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds()};k.m=(k.n<10?"0":"")+k.n;k.d=(k.j<10?"0":"")+k.j;k.A=k.a.toString().toUpperCase();k.h=(k.g<10?"0":"")+k.g;k.H=(k.G<10?"0":"")+k.G;k.i=(k.i<10?"0":"")+k.i;k.s=(k.s<10?"0":"")+k.s}else{throw new Error("Invalid format type.")}}var l=[],r=d.extend([],q.separators);for(var n=0,j=q.parts.length;n<j;n++){if(r.length){l.push(r.shift())}l.push(k[q.parts[n]])}if(r.length){l.push(r.shift())}return l.join("")},convertViewMode:function(i){switch(i){case 4:case"decade":i=4;break;case 3:case"year":i=3;break;case 2:case"month":i=2;break;case 1:case"day":i=1;break;case 0:case"hour":i=0;break}return i},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};c.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplate+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+"</table></div></div>";c.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplateV3+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">
15737'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+"</table></div></div>";d.fn.datetimepicker.DPGlobal=c;d.fn.datetimepicker.noConflict=function(){d.fn.datetimepicker=b;return this};d(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(j){var i=d(this);if(i.data("datetimepicker")){return}j.preventDefault();i.datetimepicker("show")});d(function(){d('[data-provide="datetimepicker-inline"]').datetimepicker()})}));
15738/*! bootstrap-timepicker v0.5.2 
15739* http://jdewit.github.com/bootstrap-timepicker 
15740* Copyright (c) 2016 Joris de Wit and bootstrap-timepicker contributors 
15741* MIT License 
15742*/!function(a,b,c){"use strict";var d=function(b,c){this.widget="",this.$element=a(b),this.defaultTime=c.defaultTime,this.disableFocus=c.disableFocus,this.disableMousewheel=c.disableMousewheel,this.isOpen=c.isOpen,this.minuteStep=c.minuteStep,this.modalBackdrop=c.modalBackdrop,this.orientation=c.orientation,this.secondStep=c.secondStep,this.snapToStep=c.snapToStep,this.showInputs=c.showInputs,this.showMeridian=c.showMeridian,this.showSeconds=c.showSeconds,this.template=c.template,this.appendWidgetTo=c.appendWidgetTo,this.showWidgetOnAddonClick=c.showWidgetOnAddonClick,this.icons=c.icons,this.maxHours=c.maxHours,this.explicitMode=c.explicitMode,this.handleDocumentClick=function(a){var b=a.data.scope;b.$element.parent().find(a.target).length||b.$widget.is(a.target)||b.$widget.find(a.target).length||b.hideWidget()},this._init()};d.prototype={constructor:d,_init:function(){var b=this;this.showWidgetOnAddonClick&&this.$element.parent().hasClass("input-group")&&this.$element.parent().hasClass("bootstrap-timepicker")?(this.$element.parent(".input-group.bootstrap-timepicker").find(".input-group-addon").on({"click.timepicker":a.proxy(this.showWidget,this)}),this.$element.on({"focus.timepicker":a.proxy(this.highlightUnit,this),"click.timepicker":a.proxy(this.highlightUnit,this),"keydown.timepicker":a.proxy(this.elementKeydown,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)})):this.template?this.$element.on({"focus.timepicker":a.proxy(this.showWidget,this),"click.timepicker":a.proxy(this.showWidget,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)}):this.$element.on({"focus.timepicker":a.proxy(this.highlightUnit,this),"click.timepicker":a.proxy(this.highlightUnit,this),"keydown.timepicker":a.proxy(this.elementKeydown,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)}),this.template!==!1?this.$widget=a(this.getTemplate()).on("click",a.proxy(this.widgetClick,this)):this.$widget=!1,this.showInputs&&this.$widget!==!1&&this.$widget.find("input").each(function(){a(this).on({"click.timepicker":function(){a(this).select()},"keydown.timepicker":a.proxy(b.widgetKeydown,b),"keyup.timepicker":a.proxy(b.widgetKeyup,b)})}),this.setDefaultTime(this.defaultTime)},blurElement:function(){this.highlightedUnit=null,this.updateFromElementVal()},clear:function(){this.hour="",this.minute="",this.second="",this.meridian="",this.$element.val("")},decrementHour:function(){if(this.showMeridian)if(1===this.hour)this.hour=12;else{if(12===this.hour)return this.hour--,this.toggleMeridian();if(0===this.hour)return this.hour=11,this.toggleMeridian();this.hour--}else this.hour<=0?this.hour=this.maxHours-1:this.hour--},decrementMinute:function(a){var b;b=a?this.minute-a:this.minute-this.minuteStep,0>b?(this.decrementHour(),this.minute=b+60):this.minute=b},decrementSecond:function(){var a=this.second-this.secondStep;0>a?(this.decrementMinute(!0),this.second=a+60):this.second=a},elementKeydown:function(a){switch(a.which){case 9:if(a.shiftKey){if("hour"===this.highlightedUnit){this.hideWidget();break}this.highlightPrevUnit()}else{if(this.showMeridian&&"meridian"===this.highlightedUnit||this.showSeconds&&"second"===this.highlightedUnit||!this.showMeridian&&!this.showSeconds&&"minute"===this.highlightedUnit){this.hideWidget();break}this.highlightNextUnit()}a.preventDefault(),this.updateFromElementVal();break;case 27:this.updateFromElementVal();break;case 37:a.preventDefault(),this.highlightPrevUnit(),this.updateFromElementVal();break;case 38:switch(a.preventDefault(),this.highlightedUnit){case"hour":this.incrementHour(),this.highlightHour();break;case"minute":this.incrementMinute(),this.highlightMinute();break;case"second":this.incrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian()}this.update();break;case 39:a.preventDefault(),this.highlightNextUnit(),this.updateFromElementVal();break;case 40:switch(a.preventDefault(),this.highlightedUnit){case"hour":this.decrementHour(),this.highlightHour();break;case"minute":this.decrementMinute(),this.highlightMinute();break;case"second":this.decrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian()}this.update()}},getCursorPosition:function(){var a=this.$element.get(0);if("selectionStart"in a)return a.selectionStart;if(c.selection){a.focus();var b=c.selection.createRange(),d=c.selection.createRange().text.length;return b.moveStart("character",-a.value.length),b.text.length-d}},getTemplate:function(){var a,b,c,d,e,f;switch(this.showInputs?(b='<input type="text" class="bootstrap-timepicker-hour" maxlength="2"/>',c='<input type="text" class="bootstrap-timepicker-minute" maxlength="2"/>',d='<input type="text" class="bootstrap-timepicker-second" maxlength="2"/>',e='<input type="text" class="bootstrap-timepicker-meridian" maxlength="2"/>'):(b='<span class="bootstrap-timepicker-hour"></span>',c='<span class="bootstrap-timepicker-minute"></span>',d='<span class="bootstrap-timepicker-second"></span>',e='<span class="bootstrap-timepicker-meridian"></span>'),f='<table><tr><td><a href="#" data-action="incrementHour"><span class="'+this.icons.up+'"></span></a></td><td class="separator">&nbsp;</td><td><a href="#" data-action="incrementMinute"><span class="'+this.icons.up+'"></span></a></td>'+(this.showSeconds?'<td class="separator">&nbsp;</td><td><a href="#" data-action="incrementSecond"><span class="'+this.icons.up+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator">&nbsp;</td><td class="meridian-column"><a href="#" data-action="toggleMeridian"><span class="'+this.icons.up+'"></span></a></td>':"")+"</tr><tr><td>"+b+'</td> <td class="separator">:</td><td>'+c+"</td> "+(this.showSeconds?'<td class="separator">:</td><td>'+d+"</td>":"")+(this.showMeridian?'<td class="separator">&nbsp;</td><td>'+e+"</td>":"")+'</tr><tr><td><a href="#" data-action="decrementHour"><span class="'+this.icons.down+'"></span></a></td><td class="separator"></td><td><a href="#" data-action="decrementMinute"><span class="'+this.icons.down+'"></span></a></td>'+(this.showSeconds?'<td class="separator">&nbsp;</td><td><a href="#" data-action="decrementSecond"><span class="'+this.icons.down+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator">&nbsp;</td><td><a href="#" data-action="toggleMeridian"><span class="'+this.icons.down+'"></span></a></td>':"")+"</tr></table>",this.template){case"modal":a='<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+(this.modalBackdrop?"true":"false")+'"><div class="modal-header"><a href="#" class="close" data-dismiss="modal">&times;</a><h3>
15742Pick a Time</h3></div><div class="modal-content">'+f+'</div><div class="modal-footer"><a href="#" class="btn btn-primary" data-dismiss="modal">OK</a></div></div>';break;case"dropdown":a='<div class="bootstrap-timepicker-widget dropdown-menu">'+f+"</div>"}return a},getTime:function(){return""===this.hour?"":this.hour+":"+(1===this.minute.toString().length?"0"+this.minute:this.minute)+(this.showSeconds?":"+(1===this.second.toString().length?"0"+this.second:this.second):"")+(this.showMeridian?" "+this.meridian:"")},hideWidget:function(){this.isOpen!==!1&&(this.$element.trigger({type:"hide.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}}),"modal"===this.template&&this.$widget.modal?this.$widget.modal("hide"):this.$widget.removeClass("open"),a(c).off("mousedown.timepicker, touchend.timepicker",this.handleDocumentClick),this.isOpen=!1,this.$widget.detach())},highlightUnit:function(){this.position=this.getCursorPosition(),this.position>=0&&this.position<=2?this.highlightHour():this.position>=3&&this.position<=5?this.highlightMinute():this.position>=6&&this.position<=8?this.showSeconds?this.highlightSecond():this.highlightMeridian():this.position>=9&&this.position<=11&&this.highlightMeridian()},highlightNextUnit:function(){switch(this.highlightedUnit){case"hour":this.highlightMinute();break;case"minute":this.showSeconds?this.highlightSecond():this.showMeridian?this.highlightMeridian():this.highlightHour();break;case"second":this.showMeridian?this.highlightMeridian():this.highlightHour();break;case"meridian":this.highlightHour()}},highlightPrevUnit:function(){switch(this.highlightedUnit){case"hour":this.showMeridian?this.highlightMeridian():this.showSeconds?this.highlightSecond():this.highlightMinute();break;case"minute":this.highlightHour();break;case"second":this.highlightMinute();break;case"meridian":this.showSeconds?this.highlightSecond():this.highlightMinute()}},highlightHour:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="hour",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(0,1):a.setSelectionRange(0,2)},0)},highlightMinute:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="minute",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(2,4):a.setSelectionRange(3,5)},0)},highlightSecond:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="second",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(5,7):a.setSelectionRange(6,8)},0)},highlightMeridian:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="meridian",a.setSelectionRange&&(this.showSeconds?setTimeout(function(){b.hour<10?a.setSelectionRange(8,10):a.setSelectionRange(9,11)},0):setTimeout(function(){b.hour<10?a.setSelectionRange(5,7):a.setSelectionRange(6,8)},0))},incrementHour:function(){if(this.showMeridian){if(11===this.hour)return this.hour++,this.toggleMeridian();12===this.hour&&(this.hour=0)}return this.hour===this.maxHours-1?void(this.hour=0):void this.hour++},incrementMinute:function(a){var b;b=a?this.minute+a:this.minute+this.minuteStep-this.minute%this.minuteStep,b>59?(this.incrementHour(),this.minute=b-60):this.minute=b},incrementSecond:function(){var a=this.second+this.secondStep-this.second%this.secondStep;a>59?(this.incrementMinute(!0),this.second=a-60):this.second=a},mousewheel:function(b){if(!this.disableMousewheel){b.preventDefault(),b.stopPropagation();var c=b.originalEvent.wheelDelta||-b.originalEvent.detail,d=null;switch("mousewheel"===b.type?d=-1*b.originalEvent.wheelDelta:"DOMMouseScroll"===b.type&&(d=40*b.originalEvent.detail),d&&(b.preventDefault(),a(this).scrollTop(d+a(this).scrollTop())),this.highlightedUnit){case"minute":c>0?this.incrementMinute():this.decrementMinute(),this.highlightMinute();break;case"second":c>0?this.incrementSecond():this.decrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian();break;default:c>0?this.incrementHour():this.decrementHour(),this.highlightHour()}return!1}},changeToNearestStep:function(a,b){return a%b===0?a:Math.round(a%b/b)?(a+(b-a%b))%60:a-a%b},place:function(){if(!this.isInline){var c=this.$widget.outerWidth(),d=this.$widget.outerHeight(),e=10,f=a(b).width(),g=a(b).height(),h=a(b).scrollTop(),i=parseInt(this.$element.parents().filter(function(){return"auto"!==a(this).css("z-index")}).first().css("z-index"),10)+10,j=this.component?this.component.parent().offset():this.$element.offset(),k=this.component?this.component.outerHeight(!0):this.$element.outerHeight(!1),l=this.component?this.component.outerWidth(!0):this.$element.outerWidth(!1),m=j.left,n=j.top;this.$widget.removeClass("timepicker-orient-top timepicker-orient-bottom timepicker-orient-right timepicker-orient-left"),"auto"!==this.orientation.x?(this.$widget.addClass("timepicker-orient-"+this.orientation.x),"right"===this.orientation.x&&(m-=c-l)):(this.$widget.addClass("timepicker-orient-left"),j.left<0?m-=j.left-e:j.left+c>f&&(m=f-c-e));var o,p,q=this.orientation.y;"auto"===q&&(o=-h+j.top-d,p=h+g-(j.top+k+d),q=Math.max(o,p)===p?"top":"bottom"),this.$widget.addClass("timepicker-orient-"+q),"top"===q?n+=k:n-=d+
15742parseInt(this.$widget.css("padding-top"),10),this.$widget.css({top:n,left:m,zIndex:i})}},remove:function(){a("document").off(".timepicker"),this.$widget&&this.$widget.remove(),delete this.$element.data().timepicker},setDefaultTime:function(a){if(this.$element.val())this.updateFromElementVal();else if("current"===a){var b=new Date,c=b.getHours(),d=b.getMinutes(),e=b.getSeconds(),f="AM";0!==e&&(e=Math.ceil(b.getSeconds()/this.secondStep)*this.secondStep,60===e&&(d+=1,e=0)),0!==d&&(d=Math.ceil(b.getMinutes()/this.minuteStep)*this.minuteStep,60===d&&(c+=1,d=0)),this.showMeridian&&(0===c?c=12:c>=12?(c>12&&(c-=12),f="PM"):f="AM"),this.hour=c,this.minute=d,this.second=e,this.meridian=f,this.update()}else a===!1?(this.hour=0,this.minute=0,this.second=0,this.meridian="AM"):this.setTime(a)},setTime:function(a,b){if(!a)return void this.clear();var c,d,e,f,g,h;if("object"==typeof a&&a.getMonth)e=a.getHours(),f=a.getMinutes(),g=a.getSeconds(),this.showMeridian&&(h="AM",e>12&&(h="PM",e%=12),12===e&&(h="PM"));else{if(c=(/a/i.test(a)?1:0)+(/p/i.test(a)?2:0),c>2)return void this.clear();if(d=a.replace(/[^0-9\:]/g,"").split(":"),e=d[0]?d[0].toString():d.toString(),this.explicitMode&&e.length>2&&e.length%2!==0)return void this.clear();f=d[1]?d[1].toString():"",g=d[2]?d[2].toString():"",e.length>4&&(g=e.slice(-2),e=e.slice(0,-2)),e.length>2&&(f=e.slice(-2),e=e.slice(0,-2)),f.length>2&&(g=f.slice(-2),f=f.slice(0,-2)),e=parseInt(e,10),f=parseInt(f,10),g=parseInt(g,10),isNaN(e)&&(e=0),isNaN(f)&&(f=0),isNaN(g)&&(g=0),g>59&&(g=59),f>59&&(f=59),e>=this.maxHours&&(e=this.maxHours-1),this.showMeridian?(e>12&&(c=2,e-=12),c||(c=1),0===e&&(e=12),h=1===c?"AM":"PM"):12>e&&2===c?e+=12:e>=this.maxHours?e=this.maxHours-1:(0>e||12===e&&1===c)&&(e=0)}this.hour=e,this.snapToStep?(this.minute=this.changeToNearestStep(f,this.minuteStep),this.second=this.changeToNearestStep(g,this.secondStep)):(this.minute=f,this.second=g),this.meridian=h,this.update(b)},showWidget:function(){this.isOpen||this.$element.is(":disabled")||(this.$widget.appendTo(this.appendWidgetTo),a(c).on("mousedown.timepicker, touchend.timepicker",{scope:this},this.handleDocumentClick),this.$element.trigger({type:"show.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}}),this.place(),this.disableFocus&&this.$element.blur(),""===this.hour&&(this.defaultTime?this.setDefaultTime(this.defaultTime):this.setTime("0:0:0")),"modal"===this.template&&this.$widget.modal?this.$widget.modal("show").on("hidden",a.proxy(this.hideWidget,this)):this.isOpen===!1&&this.$widget.addClass("open"),this.isOpen=!0)},toggleMeridian:function(){this.meridian="AM"===this.meridian?"PM":"AM"},update:function(a){this.updateElement(),a||this.updateWidget(),this.$element.trigger({type:"changeTime.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}})},updateElement:function(){this.$element.val(this.getTime()).change()},updateFromElementVal:function(){this.setTime(this.$element.val())},updateWidget:function(){if(this.$widget!==!1){var a=this.hour,b=1===this.minute.toString().length?"0"+this.minute:this.minute,c=1===this.second.toString().length?"0"+this.second:this.second;this.showInputs?(this.$widget.find("input.bootstrap-timepicker-hour").val(a),this.$widget.find("input.bootstrap-timepicker-minute").val(b),this.showSeconds&&this.$widget.find("input.bootstrap-timepicker-second").val(c),this.showMeridian&&this.$widget.find("input.bootstrap-timepicker-meridian").val(this.meridian)):(this.$widget.find("span.bootstrap-timepicker-hour").text(a),this.$widget.find("span.bootstrap-timepicker-minute").text(b),this.showSeconds&&this.$widget.find("span.bootstrap-timepicker-second").text(c),this.showMeridian&&this.$widget.find("span.bootstrap-timepicker-meridian").text(this.meridian))}},updateFromWidgetInputs:function(){if(this.$widget!==!1){var a=this.$widget.find("input.bootstrap-timepicker-hour").val()+":"+this.$widget.find("input.bootstrap-timepicker-minute").val()+(this.showSeconds?":"+this.$widget.find("input.bootstrap-timepicker-second").val():"")+(this.showMeridian?this.$widget.find("input.bootstrap-timepicker-meridian").val():"");this.setTime(a,!0)}},widgetClick:function(b){b.stopPropagation(),b.preventDefault();var c=a(b.target),d=c.closest("a").data("action");d&&this[d](),this.update(),c.is("input")&&c.get(0).setSelectionRange(0,2)},widgetKeydown:function(b){var c=a(b.target),d=c.attr("class").replace("bootstrap-timepicker-","");
15742switch(b.which){case 9:if(b.shiftKey){if("hour"===d)return this.hideWidget()}else if(this.showMeridian&&"meridian"===d||this.showSeconds&&"second"===d||!this.showMeridian&&!this.showSeconds&&"minute"===d)return this.hideWidget();break;case 27:this.hideWidget();break;case 38:switch(b.preventDefault(),d){case"hour":this.incrementHour();break;case"minute":this.incrementMinute();break;case"second":this.incrementSecond();break;case"meridian":this.toggleMeridian()}this.setTime(this.getTime()),c.get(0).setSelectionRange(0,2);break;case 40:switch(b.preventDefault(),d){case"hour":this.decrementHour();break;case"minute":this.decrementMinute();break;case"second":this.decrementSecond();break;case"meridian":this.toggleMeridian()}this.setTime(this.getTime()),c.get(0).setSelectionRange(0,2)}},widgetKeyup:function(a){(65===a.which||77===a.which||80===a.which||46===a.which||8===a.which||a.which>=48&&a.which<=57||a.which>=96&&a.which<=105)&&this.updateFromWidgetInputs()}},a.fn.timepicker=function(b){var c=Array.apply(null,arguments);return c.shift(),this.each(function(){var e=a(this),f=e.data("timepicker"),g="object"==typeof b&&b;f||e.data("timepicker",f=new d(this,a.extend({},a.fn.timepicker.defaults,g,a(this).data()))),"string"==typeof b&&f[b].apply(f,c)})},a.fn.timepicker.defaults={defaultTime:"current",disableFocus:!1,disableMousewheel:!1,isOpen:!1,minuteStep:15,modalBackdrop:!1,orientation:{x:"auto",y:"auto"},secondStep:15,snapToStep:!1,showSeconds:!1,showInputs:!0,showMeridian:!0,template:"dropdown",appendWidgetTo:"body",showWidgetOnAddonClick:!0,icons:{up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down"},maxHours:24,explicitMode:!1},a.fn.timepicker.Constructor=d,a(c).on("focus.timepicker.data-api click.timepicker.data-api",'[data-provide="timepicker"]',function(b){var c=a(this);c.data("timepicker")||(b.preventDefault(),c.timepicker())})}(jQuery,window,document);
15743"use strict";
15744$.fn.timepicker.defaults = $.extend(true, {}, $.fn.timepicker.defaults, {
15745    icons: {
15746        up: 'la la-angle-up',
15747        down: 'la la-angle-down'  
15748    }
15749});
15750/**
15751* @version: 3.0.5
15752* @author: Dan Grossman http://www.dangrossman.info/
15753* @copyright: Copyright (c) 2012-2019 Dan Grossman. All rights reserved.
15754* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
15755* @website: http://www.daterangepicker.com/
15756*/
15757// Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js
15758(function (root, factory) {
15759    if (typeof define === 'function' && define.amd) {
15760        // AMD. Make globaly available as well
15761        define(['moment', 'jquery'], function (moment, jquery) {
15762            if (!jquery.fn) jquery.fn = {}; // webpack server rendering
15763            if (typeof moment !== 'function' && moment.default) moment = moment.default
15764            return factory(moment, jquery);
15765        });
15766    } else if (typeof module === 'object' && module.exports) {
15767        // Node / Browserify
15768        //isomorphic issue
15769        var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined;
15770        if (!jQuery) {
15771            jQuery = require('jquery');
15772            if (!jQuery.fn) jQuery.fn = {};
15773        }
15774        var moment = (typeof window != 'undefined' && typeof window.moment != 'undefined') ? window.moment : require('moment');
15775        module.exports = factory(moment, jQuery);
15776    } else {
15777        // Browser globals
15778        root.daterangepicker = factory(root.moment, root.jQuery);
15779    }
15780}(this, function(moment, $) {
15781    var DateRangePicker = function(element, options, cb) {
15782
15783        //default settings for options
15784        this.parentEl = 'body';
15785        this.element = $(element);
15786        this.startDate = moment().startOf('day');
15787        this.endDate = moment().endOf('day');
15788        this.minDate = false;
15789        this.maxDate = false;
15790        this.maxSpan = false;
15791        this.autoApply = false;
15792        this.singleDatePicker = false;
15793        this.showDropdowns = false;
15794        this.minYear = moment().subtract(100, 'year').format('YYYY');
15795        this.maxYear = moment().add(100, 'year').format('YYYY');
15796        this.showWeekNumbers = false;
vendor: 64,818 bytes, lines 15797-17359
15797        this.showISOWeekNumbers = false;
15798        this.showCustomRangeLabel = true;
15799        this.timePicker = false;
15800        this.timePicker24Hour = false;
15801        this.timePickerIncrement = 1;
15802        this.timePickerSeconds = false;
15803        this.linkedCalendars = true;
15804        this.autoUpdateInput = true;
15805        this.alwaysShowCalendars = false;
15806        this.ranges = {};
15807
15808        this.opens = 'right';
15809        if (this.element.hasClass('pull-right'))
15810            this.opens = 'left';
15811
15812        this.drops = 'down';
15813        if (this.element.hasClass('dropup'))
15814            this.drops = 'up';
15815
15816        this.buttonClasses = 'btn btn-sm';
15817        this.applyButtonClasses = 'btn-primary';
15818        this.cancelButtonClasses = 'btn-default';
15819
15820        this.locale = {
15821            direction: 'ltr',
15822            format: moment.localeData().longDateFormat('L'),
15823            separator: ' - ',
15824            applyLabel: 'Apply',
15825            cancelLabel: 'Cancel',
15826            weekLabel: 'W',
15827            customRangeLabel: 'Custom Range',
15828            daysOfWeek: moment.weekdaysMin(),
15829            monthNames: moment.monthsShort(),
15830            firstDay: moment.localeData().firstDayOfWeek()
15831        };
15832
15833        this.callback = function() { };
15834
15835        //some state information
15836        this.isShowing = false;
15837        this.leftCalendar = {};
15838        this.rightCalendar = {};
15839
15840        //custom options from user
15841        if (typeof options !== 'object' || options === null)
15842            options = {};
15843
15844        //allow setting options with data attributes
15845        //data-api options will be overwritten with custom javascript options
15846        options = $.extend(this.element.data(), options);
15847
15848        //html template for the picker UI
15849        if (typeof options.template !== 'string' && !(options.template instanceof $))
15850            options.template =
15851            '<div class="daterangepicker">' +
15852                '<div class="ranges"></div>' +
15853                '<div class="drp-calendar left">' +
15854                    '<div class="calendar-table"></div>' +
15855                    '<div class="calendar-time"></div>' +
15856                '</div>' +
15857                '<div class="drp-calendar right">' +
15858                    '<div class="calendar-table"></div>' +
15859                    '<div class="calendar-time"></div>' +
15860                '</div>' +
15861                '<div class="drp-buttons">' +
15862                    '<span class="drp-selected"></span>' +
15863                    '<button class="cancelBtn" type="button"></button>' +
15864                    '<button class="applyBtn" disabled="disabled" type="button"></button> ' +
15865                '</div>' +
15866            '</div>';
15867
15868        this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);
15869        this.container = $(options.template).appendTo(this.parentEl);
15870
15871        //
15872        // handle all the possible options overriding defaults
15873        //
15874
15875        if (typeof options.locale === 'object') {
15876
15877            if (typeof options.locale.direction === 'string')
15878                this.locale.direction = options.locale.direction;
15879
15880            if (typeof options.locale.format === 'string')
15881                this.locale.format = options.locale.format;
15882
15883            if (typeof options.locale.separator === 'string')
15884                this.locale.separator = options.locale.separator;
15885
15886            if (typeof options.locale.daysOfWeek === 'object')
15887                this.locale.daysOfWeek = options.locale.daysOfWeek.slice();
15888
15889            if (typeof options.locale.monthNames === 'object')
15890              this.locale.monthNames = options.locale.monthNames.slice();
15891
15892            if (typeof options.locale.firstDay === 'number')
15893              this.locale.firstDay = options.locale.firstDay;
15894
15895            if (typeof options.locale.applyLabel === 'string')
15896              this.locale.applyLabel = options.locale.applyLabel;
15897
15898            if (typeof options.locale.cancelLabel === 'string')
15899              this.locale.cancelLabel = options.locale.cancelLabel;
15900
15901            if (typeof options.locale.weekLabel === 'string')
15902              this.locale.weekLabel = options.locale.weekLabel;
15903
15904            if (typeof options.locale.customRangeLabel === 'string'){
15905                //Support unicode chars in the custom range name.
15906                var elem = document.createElement('textarea');
15907                elem.innerHTML = options.locale.customRangeLabel;
15908                var rangeHtml = elem.value;
15909                this.locale.customRangeLabel = rangeHtml;
15910            }
15911        }
15912        this.container.addClass(this.locale.direction);
15913
15914        if (typeof options.startDate === 'string')
15915            this.startDate = moment(options.startDate, this.locale.format);
15916
15917        if (typeof options.endDate === 'string')
15918            this.endDate = moment(options.endDate, this.locale.format);
15919
15920        if (typeof options.minDate === 'string')
15921            this.minDate = moment(options.minDate, this.locale.format);
15922
15923        if (typeof options.maxDate === 'string')
15924            this.maxDate = moment(options.maxDate, this.locale.format);
15925
15926        if (typeof options.startDate === 'object')
15927            this.startDate = moment(options.startDate);
15928
15929        if (typeof options.endDate === 'object')
15930            this.endDate = moment(options.endDate);
15931
15932        if (typeof options.minDate === 'object')
15933            this.minDate = moment(options.minDate);
15934
15935        if (typeof options.maxDate === 'object')
15936            this.maxDate = moment(options.maxDate);
15937
15938        // sanity check for bad options
15939        if (this.minDate && this.startDate.isBefore(this.minDate))
15940            this.startDate = this.minDate.clone();
15941
15942        // sanity check for bad options
15943        if (this.maxDate && this.endDate.isAfter(this.maxDate))
15944            this.endDate = this.maxDate.clone();
15945
15946        if (typeof options.applyButtonClasses === 'string')
15947            this.applyButtonClasses = options.applyButtonClasses;
15948
15949        if (typeof options.applyClass === 'string') //backwards compat
15950            this.applyButtonClasses = options.applyClass;
15951
15952        if (typeof options.cancelButtonClasses === 'string')
15953            this.cancelButtonClasses = options.cancelButtonClasses;
15954
15955        if (typeof options.cancelClass === 'string') //backwards compat
15956            this.cancelButtonClasses = options.cancelClass;
15957
15958        if (typeof options.maxSpan === 'object')
15959            this.maxSpan = options.maxSpan;
15960
15961        if (typeof options.dateLimit === 'object') //backwards compat
15962            this.maxSpan = options.dateLimit;
15963
15964        if (typeof options.opens === 'string')
15965            this.opens = options.opens;
15966
15967        if (typeof options.drops === 'string')
15968            this.drops = options.drops;
15969
15970        if (typeof options.showWeekNumbers === 'boolean')
15971            this.showWeekNumbers = options.showWeekNumbers;
15972
15973        if (typeof options.showISOWeekNumbers === 'boolean')
15974            this.showISOWeekNumbers = options.showISOWeekNumbers;
15975
15976        if (typeof options.buttonClasses === 'string')
15977            this.buttonClasses = options.buttonClasses;
15978
15979        if (typeof options.buttonClasses === 'object')
15980            this.buttonClasses = options.buttonClasses.join(' ');
15981
15982        if (typeof options.showDropdowns === 'boolean')
15983            this.showDropdowns = options.showDropdowns;
15984
15985        if (typeof options.minYear === 'number')
15986            this.minYear = options.minYear;
15987
15988        if (typeof options.maxYear === 'number')
15989            this.maxYear = options.maxYear;
15990
15991        if (typeof options.showCustomRangeLabel === 'boolean')
15992            this.showCustomRangeLabel = options.showCustomRangeLabel;
15993
15994        if (typeof options.singleDatePicker === 'boolean') {
15995            this.singleDatePicker = options.singleDatePicker;
15996            if (this.singleDatePicker)
15997                this.endDate = this.startDate.clone();
15998        }
15999
16000        if (typeof options.timePicker === 'boolean')
16001            this.timePicker = options.timePicker;
16002
16003        if (typeof options.timePickerSeconds === 'boolean')
16004            this.timePickerSeconds = options.timePickerSeconds;
16005
16006        if (typeof options.timePickerIncrement === 'number')
16007            this.timePickerIncrement = options.timePickerIncrement;
16008
16009        if (typeof options.timePicker24Hour === 'boolean')
16010            this.timePicker24Hour = options.timePicker24Hour;
16011
16012        if (typeof options.autoApply === 'boolean')
16013            this.autoApply = options.autoApply;
16014
16015        if (typeof options.autoUpdateInput === 'boolean')
16016            this.autoUpdateInput = options.autoUpdateInput;
16017
16018        if (typeof options.linkedCalendars === 'boolean')
16019            this.linkedCalendars = options.linkedCalendars;
16020
16021        if (typeof options.isInvalidDate === 'function')
16022            this.isInvalidDate = options.isInvalidDate;
16023
16024        if (typeof options.isCustomDate === 'function')
16025            this.isCustomDate = options.isCustomDate;
16026
16027        if (typeof options.alwaysShowCalendars === 'boolean')
16028            this.alwaysShowCalendars = options.alwaysShowCalendars;
16029
16030        // update day names order to firstDay
16031        if (this.locale.firstDay != 0) {
16032            var iterator = this.locale.firstDay;
16033            while (iterator > 0) {
16034                this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());
16035                iterator--;
16036            }
16037        }
16038
16039        var start, end, range;
16040
16041        //if no start/end dates set, check if an input element contains initial values
16042        if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {
16043            if ($(this.element).is(':text')) {
16044                var val = $(this.element).val(),
16045                    split = val.split(this.locale.separator);
16046
16047                start = end = null;
16048
16049                if (split.length == 2) {
16050                    start = moment(split[0], this.locale.format);
16051                    end = moment(split[1], this.locale.format);
16052                } else if (this.singleDatePicker && val !== "") {
16053                    start = moment(val, this.locale.format);
16054                    end = moment(val, this.locale.format);
16055                }
16056                if (start !== null && end !== null) {
16057                    this.setStartDate(start);
16058                    this.setEndDate(end);
16059                }
16060            }
16061        }
16062
16063        if (typeof options.ranges === 'object') {
16064            for (range in options.ranges) {
16065
16066                if (typeof options.ranges[range][0] === 'string')
16067                    start = moment(options.ranges[range][0], this.locale.format);
16068                else
16069                    start = moment(options.ranges[range][0]);
16070
16071                if (typeof options.ranges[range][1] === 'string')
16072                    end = moment(options.ranges[range][1], this.locale.format);
16073                else
16074                    end = moment(options.ranges[range][1]);
16075
16076                // If the start or end date exceed those allowed by the minDate or maxSpan
16077                // options, shorten the range to the allowable period.
16078                if (this.minDate && start.isBefore(this.minDate))
16079                    start = this.minDate.clone();
16080
16081                var maxDate = this.maxDate;
16082                if (this.maxSpan && maxDate && start.clone().add(this.maxSpan).isAfter(maxDate))
16083                    maxDate = start.clone().add(this.maxSpan);
16084                if (maxDate && end.isAfter(maxDate))
16085                    end = maxDate.clone();
16086
16087                // If the end of the range is before the minimum or the start of the range is
16088                // after the maximum, don't display this range option at all.
16089                if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day'))
16090                  || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day')))
16091                    continue;
16092
16093                //Support unicode chars in the range names.
16094                var elem = document.createElement('textarea');
16095                elem.innerHTML = range;
16096                var rangeHtml = elem.value;
16097
16098                this.ranges[rangeHtml] = [start, end];
16099            }
16100
16101            var list = '<ul>';
16102            for (range in this.ranges) {
16103                list += '<li data-range-key="' + range + '">' + range + '</li>';
16104            }
16105            if (this.showCustomRangeLabel) {
16106                list += '<li data-range-key="' + this.locale.customRangeLabel + '">' + this.locale.customRangeLabel + '</li>';
16107            }
16108            list += '</ul>';
16109            this.container.find('.ranges').prepend(list);
16110        }
16111
16112        if (typeof cb === 'function') {
16113            this.callback = cb;
16114        }
16115
16116        if (!this.timePicker) {
16117            this.startDate = this.startDate.startOf('day');
16118            this.endDate = this.endDate.endOf('day');
16119            this.container.find('.calendar-time').hide();
16120        }
16121
16122        //can't be used together for now
16123        if (this.timePicker && this.autoApply)
16124            this.autoApply = false;
16125
16126        if (this.autoApply) {
16127            this.container.addClass('auto-apply');
16128        }
16129
16130        if (typeof options.ranges === 'object')
16131            this.container.addClass('show-ranges');
16132
16133        if (this.singleDatePicker) {
16134            this.container.addClass('single');
16135            this.container.find('.drp-calendar.left').addClass('single');
16136            this.container.find('.drp-calendar.left').show();
16137            this.container.find('.drp-calendar.right').hide();
16138            if (!this.timePicker) {
16139                this.container.addClass('auto-apply');
16140            }
16141        }
16142
16143        if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) {
16144            this.container.addClass('show-calendar');
16145        }
16146
16147        this.container.addClass('opens' + this.opens);
16148
16149        //apply CSS classes and labels to buttons
16150        this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses);
16151        if (this.applyButtonClasses.length)
16152            this.container.find('.applyBtn').addClass(this.applyButtonClasses);
16153        if (this.cancelButtonClasses.length)
16154            this.container.find('.cancelBtn').addClass(this.cancelButtonClasses);
16155        this.container.find('.applyBtn').html(this.locale.applyLabel);
16156        this.container.find('.cancelBtn').html(this.locale.cancelLabel);
16157
16158        //
16159        // event listeners
16160        //
16161
16162        this.container.find('.drp-calendar')
16163            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))
16164            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))
16165            .on('mousedown.daterangepicker', 'td.available', $.proxy(this.clickDate, this))
16166            .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this))
16167            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this))
16168            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this))
16169            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this))
16170
16171        this.container.find('.ranges')
16172            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
16173
16174        this.container.find('.drp-buttons')
16175            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))
16176            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))
16177
16178        if (this.element.is('input') || this.element.is('button')) {
16179            this.element.on({
16180                'click.daterangepicker': $.proxy(this.show, this),
16181                'focus.daterangepicker': $.proxy(this.show, this),
16182                'keyup.daterangepicker': $.proxy(this.elementChanged, this),
16183                'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility
16184            });
16185        } else {
16186            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));
16187            this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this));
16188        }
16189
16190        //
16191        // if attached to a text input, set the initial value
16192        //
16193
16194        this.updateElement();
16195
16196    };
16197
16198    DateRangePicker.prototype = {
16199
16200        constructor: DateRangePicker,
16201
16202        setStartDate: function(startDate) {
16203            if (typeof startDate === 'string')
16204                this.startDate = moment(startDate, this.locale.format);
16205
16206            if (typeof startDate === 'object')
16207                this.startDate = moment(startDate);
16208
16209            if (!this.timePicker)
16210                this.startDate = this.startDate.startOf('day');
16211
16212            if (this.timePicker && this.timePickerIncrement)
16213                this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
16214
16215            if (this.minDate && this.startDate.isBefore(this.minDate)) {
16216                this.startDate = this.minDate.clone();
16217                if (this.timePicker && this.timePickerIncrement)
16218                    this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
16219            }
16220
16221            if (this.maxDate && this.startDate.isAfter(this.maxDate)) {
16222                this.startDate = this.maxDate.clone();
16223                if (this.timePicker && this.timePickerIncrement)
16224                    this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
16225            }
16226
16227            if (!this.isShowing)
16228                this.updateElement();
16229
16230            this.updateMonthsInView();
16231        },
16232
16233        setEndDate: function(endDate) {
16234            if (typeof endDate === 'string')
16235                this.endDate = moment(endDate, this.locale.format);
16236
16237            if (typeof endDate === 'object')
16238                this.endDate = moment(endDate);
16239
16240            if (!this.timePicker)
16241                this.endDate = this.endDate.endOf('day');
16242
16243            if (this.timePicker && this.timePickerIncrement)
16244                this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
16245
16246            if (this.endDate.isBefore(this.startDate))
16247                this.endDate = this.startDate.clone();
16248
16249            if (this.maxDate && this.endDate.isAfter(this.maxDate))
16250                this.endDate = this.maxDate.clone();
16251
16252            if (this.maxSpan && this.startDate.clone().add(this.maxSpan).isBefore(this.endDate))
16253                this.endDate = this.startDate.clone().add(this.maxSpan);
16254
16255            this.previousRightTime = this.endDate.clone();
16256
16257            this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
16258
16259            if (!this.isShowing)
16260                this.updateElement();
16261
16262            this.updateMonthsInView();
16263        },
16264
16265        isInvalidDate: function() {
16266            return false;
16267        },
16268
16269        isCustomDate: function() {
16270            return false;
16271        },
16272
16273        updateView: function() {
16274            if (this.timePicker) {
16275                this.renderTimePicker('left');
16276                this.renderTimePicker('right');
16277                if (!this.endDate) {
16278                    this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled');
16279                } else {
16280                    this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled');
16281                }
16282            }
16283            if (this.endDate)
16284                this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
16285            this.updateMonthsInView();
16286            this.updateCalendars();
16287            this.updateFormInputs();
16288        },
16289
16290        updateMonthsInView: function() {
16291            if (this.endDate) {
16292
16293                //if both dates are visible already, do nothing
16294                if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month &&
16295                    (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))
16296                    &&
16297                    (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))
16298                    ) {
16299                    return;
16300                }
16301
16302                this.leftCalendar.month = this.startDate.clone().date(2);
16303                if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) {
16304                    this.rightCalendar.month = this.endDate.clone().date(2);
16305                } else {
16306                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
16307                }
16308
16309            } else {
16310                if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) {
16311                    this.leftCalendar.month = this.startDate.clone().date(2);
16312                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
16313                }
16314            }
16315            if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) {
16316              this.rightCalendar.month = this.maxDate.clone().date(2);
16317              this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month');
16318            }
16319        },
16320
16321        updateCalendars: function() {
16322
16323            if (this.timePicker) {
16324                var hour, minute, second;
16325                if (this.endDate) {
16326                    hour = parseInt(this.container.find('.left .hourselect').val(), 10);
16327                    minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
16328                    if (isNaN(minute)) {
16329                        minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10);
16330                    }
16331                    second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
16332                    if (!this.timePicker24Hour) {
16333                        var ampm = this.container.find('.left .ampmselect').val();
16334                        if (ampm === 'PM' && hour < 12)
16335                            hour += 12;
16336                        if (ampm === 'AM' && hour === 12)
16337                            hour = 0;
16338                    }
16339                } else {
16340                    hour = parseInt(this.container.find('.right .hourselect').val(), 10);
16341                    minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
16342                    if (isNaN(minute)) {
16343                        minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10);
16344                    }
16345                    second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
16346                    if (!this.timePicker24Hour) {
16347                        var ampm = this.container.find('.right .ampmselect').val();
16348                        if (ampm === 'PM' && hour < 12)
16349                            hour += 12;
16350                        if (ampm === 'AM' && hour === 12)
16351                            hour = 0;
16352                    }
16353                }
16354                this.leftCalendar.month.hour(hour).minute(minute).second(second);
16355                this.rightCalendar.month.hour(hour).minute(minute).second(second);
16356            }
16357
16358            this.renderCalendar('left');
16359            this.renderCalendar('right');
16360
16361            //highlight any predefined range matching the current start and end dates
16362            this.container.find('.ranges li').removeClass('active');
16363            if (this.endDate == null) return;
16364
16365            this.calculateChosenLabel();
16366        },
16367
16368        renderCalendar: function(side) {
16369
16370            //
16371            // Build the matrix of dates that will populate the calendar
16372            //
16373
16374            var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar;
16375            var month = calendar.month.month();
16376            var year = calendar.month.year();
16377            var hour = calendar.month.hour();
16378            var minute = calendar.month.minute();
16379            var second = calendar.month.second();
16380            var daysInMonth = moment([year, month]).daysInMonth();
16381            var firstDay = moment([year, month, 1]);
16382            var lastDay = moment([year, month, daysInMonth]);
16383            var lastMonth = moment(firstDay).subtract(1, 'month').month();
16384            var lastYear = moment(firstDay).subtract(1, 'month').year();
16385            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();
16386            var dayOfWeek = firstDay.day();
16387
16388            //initialize a 6 rows x 7 columns array for the calendar
16389            var calendar = [];
16390            calendar.firstDay = firstDay;
16391            calendar.lastDay = lastDay;
16392
16393            for (var i = 0; i < 6; i++) {
16394                calendar[i] = [];
16395            }
16396
16397            //populate the calendar with date objects
16398            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;
16399            if (startDay > daysInLastMonth)
16400                startDay -= 7;
16401
16402            if (dayOfWeek == this.locale.firstDay)
16403                startDay = daysInLastMonth - 6;
16404
16405            var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]);
16406
16407            var col, row;
16408            for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) {
16409                if (i > 0 && col % 7 === 0) {
16410                    col = 0;
16411                    row++;
16412                }
16413                calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second);
16414                curDate.hour(12);
16415
16416                if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') {
16417                    calendar[row][col] = this.minDate.clone();
16418                }
16419
16420                if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') {
16421                    calendar[row][col] = this.maxDate.clone();
16422                }
16423
16424            }
16425
16426            //make the calendar object available to hoverDate/clickDate
16427            if (side == 'left') {
16428                this.leftCalendar.calendar = calendar;
16429            } else {
16430                this.rightCalendar.calendar = calendar;
16431            }
16432
16433            //
16434            // Display the calendar
16435            //
16436
16437            var minDate = side == 'left' ? this.minDate : this.startDate;
16438            var maxDate = this.maxDate;
16439            var selected = side == 'left' ? this.startDate : this.endDate;
16440            var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'};
16441
16442            var html = '<table class="table-condensed">';
16443            html += '<thead>';
16444            html += '<tr>';
16445
16446            // add empty cell for week number
16447            if (this.showWeekNumbers || this.showISOWeekNumbers)
16448                html += '<th></th>';
16449
16450            if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {
16451                html += '<th class="prev available"><span></span></th>';
16452            } else {
16453                html += '<th></th>';
16454            }
16455
16456            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY");
16457
16458            if (this.showDropdowns) {
16459                var currentMonth = calendar[1][1].month();
16460                var currentYear = calendar[1][1].year();
16461                var maxYear = (maxDate && maxDate.year()) || (this.maxYear);
16462                var minYear = (minDate && minDate.year()) || (this.minYear);
16463                var inMinYear = currentYear == minYear;
16464                var inMaxYear = currentYear == maxYear;
16465
16466                var monthHtml = '<select class="monthselect">';
16467                for (var m = 0; m < 12; m++) {
16468                    if ((!inMinYear || (minDate && m >= minDate.month())) && (!inMaxYear || (maxDate && m <= maxDate.month()))) {
16469                        monthHtml += "<option value='" + m + "'" +
16470                            (m === currentMonth ? " selected='selected'" : "") +
16471                            ">" + this.locale.monthNames[m] + "</option>";
16472                    } else {
16473                        monthHtml += "<option value='" + m + "'" +
16474                            (m === currentMonth ? " selected='selected'" : "") +
16475                            " disabled='disabled'>" + this.locale.monthNames[m] + "</option>";
16476                    }
16477                }
16478                monthHtml += "</select>";
16479
16480                var yearHtml = '<select class="yearselect">';
16481                for (var y = minYear; y <= maxYear; y++) {
16482                    yearHtml += '<option value="' + y + '"' +
16483                        (y === currentYear ? ' selected="selected"' : '') +
16484                        '>' + y + '</option>';
16485                }
16486                yearHtml += '</select>';
16487
16488                dateHtml = monthHtml + yearHtml;
16489            }
16490
16491            html += '<th colspan="5" class="month">' + dateHtml + '</th>';
16492            if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) {
16493                html += '<th class="next available"><span></span></th>';
16494            } else {
16495                html += '<th></th>';
16496            }
16497
16498            html += '</tr>';
16499            html += '<tr>';
16500
16501            // add week number label
16502            if (this.showWeekNumbers || this.showISOWeekNumbers)
16503                html += '<th class="week">' + this.locale.weekLabel + '</th>';
16504
16505            $.each(this.locale.daysOfWeek, function(index, dayOfWeek) {
16506                html += '<th>' + dayOfWeek + '</th>';
16507            });
16508
16509            html += '</tr>';
16510            html += '</thead>';
16511            html += '<tbody>';
16512
16513            //adjust maxDate to reflect the maxSpan setting in order to
16514            //grey out end dates beyond the maxSpan
16515            if (this.endDate == null && this.maxSpan) {
16516                var maxLimit = this.startDate.clone().add(this.maxSpan).endOf('day');
16517                if (!maxDate || maxLimit.isBefore(maxDate)) {
16518                    maxDate = maxLimit;
16519                }
16520            }
16521
16522            for (var row = 0; row < 6; row++) {
16523                html += '<tr>';
16524
16525                // add week number
16526                if (this.showWeekNumbers)
16527                    html += '<td class="week">' + calendar[row][0].week() + '</td>';
16528                else if (this.showISOWeekNumbers)
16529                    html += '<td class="week">' + calendar[row][0].isoWeek() + '</td>';
16530
16531                for (var col = 0; col < 7; col++) {
16532
16533                    var classes = [];
16534
16535                    //highlight today's date
16536                    if (calendar[row][col].isSame(new Date(), "day"))
16537                        classes.push('today');
16538
16539                    //highlight weekends
16540                    if (calendar[row][col].isoWeekday() > 5)
16541                        classes.push('weekend');
16542
16543                    //grey out the dates in other months displayed at beginning and end of this calendar
16544                    if (calendar[row][col].month() != calendar[1][1].month())
16545                        classes.push('off', 'ends');
16546
16547                    //don't allow selection of dates before the minimum date
16548                    if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day'))
16549                        classes.push('off', 'disabled');
16550
16551                    //don't allow selection of dates after the maximum date
16552                    if (maxDate && calendar[row][col].isAfter(maxDate, 'day'))
16553                        classes.push('off', 'disabled');
16554
16555                    //don't allow selection of date if a custom function decides it's invalid
16556                    if (this.isInvalidDate(calendar[row][col]))
16557                        classes.push('off', 'disabled');
16558
16559                    //highlight the currently selected start date
16560                    if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD'))
16561                        classes.push('active', 'start-date');
16562
16563                    //highlight the currently selected end date
16564                    if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD'))
16565                        classes.push('active', 'end-date');
16566
16567                    //highlight dates in-between the selected dates
16568                    if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)
16569                        classes.push('in-range');
16570
16571                    //apply custom classes for this date
16572                    var isCustom = this.isCustomDate(calendar[row][col]);
16573                    if (isCustom !== false) {
16574                        if (typeof isCustom === 'string')
16575                            classes.push(isCustom);
16576                        else
16577                            Array.prototype.push.apply(classes, isCustom);
16578                    }
16579
16580                    var cname = '', disabled = false;
16581                    for (var i = 0; i < classes.length; i++) {
16582                        cname += classes[i] + ' ';
16583                        if (classes[i] == 'disabled')
16584                            disabled = true;
16585                    }
16586                    if (!disabled)
16587                        cname += 'available';
16588
16589                    html += '<td class="' + cname.replace(/^\s+|\s+$/g, '') + '" data-title="' + 'r' + row + 'c' + col + '">' + calendar[row][col].date() + '</td>';
16590
16591                }
16592                html += '</tr>';
16593            }
16594
16595            html += '</tbody>';
16596            html += '</table>';
16597
16598            this.container.find('.drp-calendar.' + side + ' .calendar-table').html(html);
16599
16600        },
16601
16602        renderTimePicker: function(side) {
16603
16604            // Don't bother updating the time picker if it's currently disabled
16605            // because an end date hasn't been clicked yet
16606            if (side == 'right' && !this.endDate) return;
16607
16608            var html, selected, minDate, maxDate = this.maxDate;
16609
16610            if (this.maxSpan && (!this.maxDate || this.startDate.clone().add(this.maxSpan).isBefore(this.maxDate)))
16611                maxDate = this.startDate.clone().add(this.maxSpan);
16612
16613            if (side == 'left') {
16614                selected = this.startDate.clone();
16615                minDate = this.minDate;
16616            } else if (side == 'right') {
16617                selected = this.endDate.clone();
16618                minDate = this.startDate;
16619
16620                //Preserve the time already selected
16621                var timeSelector = this.container.find('.drp-calendar.right .calendar-time');
16622                if (timeSelector.html() != '') {
16623
16624                    selected.hour(!isNaN(selected.hour()) ? selected.hour() : timeSelector.find('.hourselect option:selected').val());
16625                    selected.minute(!isNaN(selected.minute()) ? selected.minute() : timeSelector.find('.minuteselect option:selected').val());
16626                    selected.second(!isNaN(selected.second()) ? selected.second() : timeSelector.find('.secondselect option:selected').val());
16627
16628                    if (!this.timePicker24Hour) {
16629                        var ampm = timeSelector.find('.ampmselect option:selected').val();
16630                        if (ampm === 'PM' && selected.hour() < 12)
16631                            selected.hour(selected.hour() + 12);
16632                        if (ampm === 'AM' && selected.hour() === 12)
16633                            selected.hour(0);
16634                    }
16635
16636                }
16637
16638                if (selected.isBefore(this.startDate))
16639                    selected = this.startDate.clone();
16640
16641                if (maxDate && selected.isAfter(maxDate))
16642                    selected = maxDate.clone();
16643
16644            }
16645
16646            //
16647            // hours
16648            //
16649
16650            html = '<select class="hourselect">';
16651
16652            var start = this.timePicker24Hour ? 0 : 1;
16653            var end = this.timePicker24Hour ? 23 : 12;
16654
16655            for (var i = start; i <= end; i++) {
16656                var i_in_24 = i;
16657                if (!this.timePicker24Hour)
16658                    i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i);
16659
16660                var time = selected.clone().hour(i_in_24);
16661                var disabled = false;
16662                if (minDate && time.minute(59).isBefore(minDate))
16663                    disabled = true;
16664                if (maxDate && time.minute(0).isAfter(maxDate))
16665                    disabled = true;
16666
16667                if (i_in_24 == selected.hour() && !disabled) {
16668                    html += '<option value="' + i + '" selected="selected">' + i + '</option>';
16669                } else if (disabled) {
16670                    html += '<option value="' + i + '" disabled="disabled" class="disabled">' + i + '</option>';
16671                } else {
16672                    html += '<option value="' + i + '">' + i + '</option>';
16673                }
16674            }
16675
16676            html += '</select> ';
16677
16678            //
16679            // minutes
16680            //
16681
16682            html += ': <select class="minuteselect">';
16683
16684            for (var i = 0; i < 60; i += this.timePickerIncrement) {
16685                var padded = i < 10 ? '0' + i : i;
16686                var time = selected.clone().minute(i);
16687
16688                var disabled = false;
16689                if (minDate && time.second(59).isBefore(minDate))
16690                    disabled = true;
16691                if (maxDate && time.second(0).isAfter(maxDate))
16692                    disabled = true;
16693
16694                if (selected.minute() == i && !disabled) {
16695                    html += '<option value="' + i + '" selected="selected">' + padded + '</option>';
16696                } else if (disabled) {
16697                    html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>';
16698                } else {
16699                    html += '<option value="' + i + '">' + padded + '</option>';
16700                }
16701            }
16702
16703            html += '</select> ';
16704
16705            //
16706            // seconds
16707            //
16708
16709            if (this.timePickerSeconds) {
16710                html += ': <select class="secondselect">';
16711
16712                for (var i = 0; i < 60; i++) {
16713                    var padded = i < 10 ? '0' + i : i;
16714                    var time = selected.clone().second(i);
16715
16716                    var disabled = false;
16717                    if (minDate && time.isBefore(minDate))
16718                        disabled = true;
16719                    if (maxDate && time.isAfter(maxDate))
16720                        disabled = true;
16721
16722                    if (selected.second() == i && !disabled) {
16723                        html += '<option value="' + i + '" selected="selected">' + padded + '</option>';
16724                    } else if (disabled) {
16725                        html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>';
16726                    } else {
16727                        html += '<option value="' + i + '">' + padded + '</option>';
16728                    }
16729                }
16730
16731                html += '</select> ';
16732            }
16733
16734            //
16735            // AM/PM
16736            //
16737
16738            if (!this.timePicker24Hour) {
16739                html += '<select class="ampmselect">';
16740
16741                var am_html = '';
16742                var pm_html = '';
16743
16744                if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate))
16745                    am_html = ' disabled="disabled" class="disabled"';
16746
16747                if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate))
16748                    pm_html = ' disabled="disabled" class="disabled"';
16749
16750                if (selected.hour() >= 12) {
16751                    html += '<option value="AM"' + am_html + '>AM</option><option value="PM" selected="selected"' + pm_html + '>PM</option>';
16752                } else {
16753                    html += '<option value="AM" selected="selected"' + am_html + '>AM</option><option value="PM"' + pm_html + '>PM</option>';
16754                }
16755
16756                html += '</select>';
16757            }
16758
16759            this.container.find('.drp-calendar.' + side + ' .calendar-time').html(html);
16760
16761        },
16762
16763        updateFormInputs: function() {
16764
16765            if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {
16766                this.container.find('button.applyBtn').removeAttr('disabled');
16767            } else {
16768                this.container.find('button.applyBtn').attr('disabled', 'disabled');
16769            }
16770
16771        },
16772
16773        move: function() {
16774            var parentOffset = { top: 0, left: 0 },
16775                containerTop;
16776            var parentRightEdge = $(window).width();
16777            if (!this.parentEl.is('body')) {
16778                parentOffset = {
16779                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),
16780                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()
16781                };
16782                parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left;
16783            }
16784
16785            if (this.drops == 'up')
16786                containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;
16787            else
16788                containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;
16789
16790            // Force the container to it's actual width
16791            this.container.css({
16792              top: 0,
16793              left: 0,
16794              right: 'auto'
16795            });
16796            var containerWidth = this.container.outerWidth();
16797
16798            this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('drop-up');
16799
16800            if (this.opens == 'left') {
16801                var containerRight = parentRightEdge - this.element.offset().left - this.element.outerWidth();
16802                if (containerWidth + containerRight > $(window).width()) {
16803                    this.container.css({
16804                        top: containerTop,
16805                        right: 'auto',
16806                        left: 9
16807                    });
16808                } else {
16809                    this.container.css({
16810                        top: containerTop,
16811                        right: containerRight,
16812                        left: 'auto'
16813                    });
16814                }
16815            } else if (this.opens == 'center') {
16816                var containerLeft = this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2
16817                                        - containerWidth / 2;
16818                if (containerLeft < 0) {
16819                    this.container.css({
16820                        top: containerTop,
16821                        right: 'auto',
16822                        left: 9
16823                    });
16824                } else if (containerLeft + containerWidth > $(window).width()) {
16825                    this.container.css({
16826                        top: containerTop,
16827                        left: 'auto',
16828                        right: 0
16829                    });
16830                } else {
16831                    this.container.css({
16832                        top: containerTop,
16833                        left: containerLeft,
16834                        right: 'auto'
16835                    });
16836                }
16837            } else {
16838                var containerLeft = this.element.offset().left - parentOffset.left;
16839                if (containerLeft + containerWidth > $(window).width()) {
16840                    this.container.css({
16841                        top: containerTop,
16842                        left: 'auto',
16843                        right: 0
16844                    });
16845                } else {
16846                    this.container.css({
16847                        top: containerTop,
16848                        left: containerLeft,
16849                        right: 'auto'
16850                    });
16851                }
16852            }
16853        },
16854
16855        show: function(e) {
16856            if (this.isShowing) return;
16857
16858            // Create a click proxy that is private to this instance of datepicker, for unbinding
16859            this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this);
16860
16861            // Bind global datepicker mousedown for hiding and
16862            $(document)
16863              .on('mousedown.daterangepicker', this._outsideClickProxy)
16864              // also support mobile devices
16865              .on('touchend.daterangepicker', this._outsideClickProxy)
16866              // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them
16867              .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)
16868              // and also close when focus changes to outside the picker (eg. tabbing between controls)
16869              .on('focusin.daterangepicker', this._outsideClickProxy);
16870
16871            // Reposition the picker if the window is resized while it's open
16872            $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this));
16873
16874            this.oldStartDate = this.startDate.clone();
16875            this.oldEndDate = this.endDate.clone();
16876            this.previousRightTime = this.endDate.clone();
16877
16878            this.updateView();
16879            this.container.show();
16880            this.move();
16881            this.element.trigger('show.daterangepicker', this);
16882            this.isShowing = true;
16883        },
16884
16885        hide: function(e) {
16886            if (!this.isShowing) return;
16887
16888            //incomplete date selection, revert to last values
16889            if (!this.endDate) {
16890                this.startDate = this.oldStartDate.clone();
16891                this.endDate = this.oldEndDate.clone();
16892            }
16893
16894            //if a new date range was selected, invoke the user callback function
16895            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
16896                this.callback(this.startDate.clone(), this.endDate.clone(), this.chosenLabel);
16897
16898            //if picker is attached to a text input, update it
16899            this.updateElement();
16900
16901            $(document).off('.daterangepicker');
16902            $(window).off('.daterangepicker');
16903            this.container.hide();
16904            this.element.trigger('hide.daterangepicker', this);
16905            this.isShowing = false;
16906        },
16907
16908        toggle: function(e) {
16909            if (this.isShowing) {
16910                this.hide();
16911            } else {
16912                this.show();
16913            }
16914        },
16915
16916        outsideClick: function(e) {
16917            var target = $(e.target);
16918            // if the page is clicked anywhere except within the daterangerpicker/button
16919            // itself then call this.hide()
16920            if (
16921                // ie modal dialog fix
16922                e.type == "focusin" ||
16923                target.closest(this.element).length ||
16924                target.closest(this.container).length ||
16925                target.closest('.calendar-table').length
16926                ) return;
16927            this.hide();
16928            this.element.trigger('outsideClick.daterangepicker', this);
16929        },
16930
16931        showCalendars: function() {
16932            this.container.addClass('show-calendar');
16933            this.move();
16934            this.element.trigger('showCalendar.daterangepicker', this);
16935        },
16936
16937        hideCalendars: function() {
16938            this.container.removeClass('show-calendar');
16939            this.element.trigger('hideCalendar.daterangepicker', this);
16940        },
16941
16942        clickRange: function(e) {
16943            var label = e.target.getAttribute('data-range-key');
16944            this.chosenLabel = label;
16945            if (label == this.locale.customRangeLabel) {
16946                this.showCalendars();
16947            } else {
16948                var dates = this.ranges[label];
16949                this.startDate = dates[0];
16950                this.endDate = dates[1];
16951
16952                if (!this.timePicker) {
16953                    this.startDate.startOf('day');
16954                    this.endDate.endOf('day');
16955                }
16956
16957                if (!this.alwaysShowCalendars)
16958                    this.hideCalendars();
16959                this.clickApply();
16960            }
16961        },
16962
16963        clickPrev: function(e) {
16964            var cal = $(e.target).parents('.drp-calendar');
16965            if (cal.hasClass('left')) {
16966                this.leftCalendar.month.subtract(1, 'month');
16967                if (this.linkedCalendars)
16968                    this.rightCalendar.month.subtract(1, 'month');
16969            } else {
16970                this.rightCalendar.month.subtract(1, 'month');
16971            }
16972            this.updateCalendars();
16973        },
16974
16975        clickNext: function(e) {
16976            var cal = $(e.target).parents('.drp-calendar');
16977            if (cal.hasClass('left')) {
16978                this.leftCalendar.month.add(1, 'month');
16979            } else {
16980                this.rightCalendar.month.add(1, 'month');
16981                if (this.linkedCalendars)
16982                    this.leftCalendar.month.add(1, 'month');
16983            }
16984            this.updateCalendars();
16985        },
16986
16987        hoverDate: function(e) {
16988
16989            //ignore dates that can't be selected
16990            if (!$(e.target).hasClass('available')) return;
16991
16992            var title = $(e.target).attr('data-title');
16993            var row = title.substr(1, 1);
16994            var col = title.substr(3, 1);
16995            var cal = $(e.target).parents('.drp-calendar');
16996            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
16997
16998            //highlight the dates between the start date and the date being hovered as a potential end date
16999            var leftCalendar = this.leftCalendar;
17000            var rightCalendar = this.rightCalendar;
17001            var startDate = this.startDate;
17002            if (!this.endDate) {
17003                this.container.find('.drp-calendar tbody td').each(function(index, el) {
17004
17005                    //skip week numbers, only look at dates
17006                    if ($(el).hasClass('week')) return;
17007
17008                    var title = $(el).attr('data-title');
17009                    var row = title.substr(1, 1);
17010                    var col = title.substr(3, 1);
17011                    var cal = $(el).parents('.drp-calendar');
17012                    var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
17013
17014                    if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) {
17015                        $(el).addClass('in-range');
17016                    } else {
17017                        $(el).removeClass('in-range');
17018                    }
17019
17020                });
17021            }
17022
17023        },
17024
17025        clickDate: function(e) {
17026
17027            if (!$(e.target).hasClass('available')) return;
17028
17029            var title = $(e.target).attr('data-title');
17030            var row = title.substr(1, 1);
17031            var col = title.substr(3, 1);
17032            var cal = $(e.target).parents('.drp-calendar');
17033            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
17034
17035            //
17036            // this function needs to do a few things:
17037            // * alternate between selecting a start and end date for the range,
17038            // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date
17039            // * if autoapply is enabled, and an end date was chosen, apply the selection
17040            // * if single date picker mode, and time picker isn't enabled, apply the selection immediately
17041            // * if one of the inputs above the calendars was focused, cancel that manual input
17042            //
17043
17044            if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start
17045                if (this.timePicker) {
17046                    var hour = parseInt(this.container.find('.left .hourselect').val(), 10);
17047                    if (!this.timePicker24Hour) {
17048                        var ampm = this.container.find('.left .ampmselect').val();
17049                        if (ampm === 'PM' && hour < 12)
17050                            hour += 12;
17051                        if (ampm === 'AM' && hour === 12)
17052                            hour = 0;
17053                    }
17054                    var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
17055                    if (isNaN(minute)) {
17056                        minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10);
17057                    }
17058                    var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
17059                    date = date.clone().hour(hour).minute(minute).second(second);
17060                }
17061                this.endDate = null;
17062                this.setStartDate(date.clone());
17063            } else if (!this.endDate && date.isBefore(this.startDate)) {
17064                //special case: clicking the same date for start/end,
17065                //but the time of the end date is before the start date
17066                this.setEndDate(this.startDate.clone());
17067            } else { // picking end
17068                if (this.timePicker) {
17069                    var hour = parseInt(this.container.find('.right .hourselect').val(), 10);
17070                    if (!this.timePicker24Hour) {
17071                        var ampm = this.container.find('.right .ampmselect').val();
17072                        if (ampm === 'PM' && hour < 12)
17073                            hour += 12;
17074                        if (ampm === 'AM' && hour === 12)
17075                            hour = 0;
17076                    }
17077                    var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
17078                    if (isNaN(minute)) {
17079                        minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10);
17080                    }
17081                    var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
17082                    date = date.clone().hour(hour).minute(minute).second(second);
17083                }
17084                this.setEndDate(date.clone());
17085                if (this.autoApply) {
17086                  this.calculateChosenLabel();
17087                  this.clickApply();
17088                }
17089            }
17090
17091            if (this.singleDatePicker) {
17092                this.setEndDate(this.startDate);
17093                if (!this.timePicker)
17094                    this.clickApply();
17095            }
17096
17097            this.updateView();
17098
17099            //This is to cancel the blur event handler if the mouse was in one of the inputs
17100            e.stopPropagation();
17101
17102        },
17103
17104        calculateChosenLabel: function () {
17105            var customRange = true;
17106            var i = 0;
17107            for (var range in this.ranges) {
17108              if (this.timePicker) {
17109                    var format = this.timePickerSeconds ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD HH:mm";
17110                    //ignore times when comparing dates if time picker seconds is not enabled
17111                    if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) {
17112                        customRange = false;
17113                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');
17114                        break;
17115                    }
17116                } else {
17117                    //ignore times when comparing dates if time picker is not enabled
17118                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {
17119                        customRange = false;
17120                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');
17121                        break;
17122                    }
17123                }
17124                i++;
17125            }
17126            if (customRange) {
17127                if (this.showCustomRangeLabel) {
17128                    this.chosenLabel = this.container.find('.ranges li:last').addClass('active').attr('data-range-key');
17129                } else {
17130                    this.chosenLabel = null;
17131                }
17132                this.showCalendars();
17133            }
17134        },
17135
17136        clickApply: function(e) {
17137            this.hide();
17138            this.element.trigger('apply.daterangepicker', this);
17139        },
17140
17141        clickCancel: function(e) {
17142            this.startDate = this.oldStartDate;
17143            this.endDate = this.oldEndDate;
17144            this.hide();
17145            this.element.trigger('cancel.daterangepicker', this);
17146        },
17147
17148        monthOrYearChanged: function(e) {
17149            var isLeft = $(e.target).closest('.drp-calendar').hasClass('left'),
17150                leftOrRight = isLeft ? 'left' : 'right',
17151                cal = this.container.find('.drp-calendar.'+leftOrRight);
17152
17153            // Month must be Number for new moment versions
17154            var month = parseInt(cal.find('.monthselect').val(), 10);
17155            var year = cal.find('.yearselect').val();
17156
17157            if (!isLeft) {
17158                if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) {
17159                    month = this.startDate.month();
17160                    year = this.startDate.year();
17161                }
17162            }
17163
17164            if (this.minDate) {
17165                if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) {
17166                    month = this.minDate.month();
17167                    year = this.minDate.year();
17168                }
17169            }
17170
17171            if (this.maxDate) {
17172                if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) {
17173                    month = this.maxDate.month();
17174                    year = this.maxDate.year();
17175                }
17176            }
17177
17178            if (isLeft) {
17179                this.leftCalendar.month.month(month).year(year);
17180                if (this.linkedCalendars)
17181                    this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month');
17182            } else {
17183                this.rightCalendar.month.month(month).year(year);
17184                if (this.linkedCalendars)
17185                    this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month');
17186            }
17187            this.updateCalendars();
17188        },
17189
17190        timeChanged: function(e) {
17191
17192            var cal = $(e.target).closest('.drp-calendar'),
17193                isLeft = cal.hasClass('left');
17194
17195            var hour = parseInt(cal.find('.hourselect').val(), 10);
17196            var minute = parseInt(cal.find('.minuteselect').val(), 10);
17197            if (isNaN(minute)) {
17198                minute = parseInt(cal.find('.minuteselect option:last').val(), 10);
17199            }
17200            var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0;
17201
17202            if (!this.timePicker24Hour) {
17203                var ampm = cal.find('.ampmselect').val();
17204                if (ampm === 'PM' && hour < 12)
17205                    hour += 12;
17206                if (ampm === 'AM' && hour === 12)
17207                    hour = 0;
17208            }
17209
17210            if (isLeft) {
17211                var start = this.startDate.clone();
17212                start.hour(hour);
17213                start.minute(minute);
17214                start.second(second);
17215                this.setStartDate(start);
17216                if (this.singleDatePicker) {
17217                    this.endDate = this.startDate.clone();
17218                } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) {
17219                    this.setEndDate(start.clone());
17220                }
17221            } else if (this.endDate) {
17222                var end = this.endDate.clone();
17223                end.hour(hour);
17224                end.minute(minute);
17225                end.second(second);
17226                this.setEndDate(end);
17227            }
17228
17229            //update the calendars so all clickable dates reflect the new time component
17230            this.updateCalendars();
17231
17232            //update the form inputs above the calendars with the new time
17233            this.updateFormInputs();
17234
17235            //re-render the time pickers because changing one selection can affect what's enabled in another
17236            this.renderTimePicker('left');
17237            this.renderTimePicker('right');
17238
17239        },
17240
17241        elementChanged: function() {
17242            if (!this.element.is('input')) return;
17243            if (!this.element.val().length) return;
17244
17245            var dateString = this.element.val().split(this.locale.separator),
17246                start = null,
17247                end = null;
17248
17249            if (dateString.length === 2) {
17250                start = moment(dateString[0], this.locale.format);
17251                end = moment(dateString[1], this.locale.format);
17252            }
17253
17254            if (this.singleDatePicker || start === null || end === null) {
17255                start = moment(this.element.val(), this.locale.format);
17256                end = start;
17257            }
17258
17259            if (!start.isValid() || !end.isValid()) return;
17260
17261            this.setStartDate(start);
17262            this.setEndDate(end);
17263            this.updateView();
17264        },
17265
17266        keydown: function(e) {
17267            //hide on tab or enter
17268            if ((e.keyCode === 9) || (e.keyCode === 13)) {
17269                this.hide();
17270            }
17271
17272            //hide on esc and prevent propagation
17273            if (e.keyCode === 27) {
17274                e.preventDefault();
17275                e.stopPropagation();
17276
17277                this.hide();
17278            }
17279        },
17280
17281        updateElement: function() {
17282            if (this.element.is('input') && this.autoUpdateInput) {
17283                var newValue = this.startDate.format(this.locale.format);
17284                if (!this.singleDatePicker) {
17285                    newValue += this.locale.separator + this.endDate.format(this.locale.format);
17286                }
17287                if (newValue !== this.element.val()) {
17288                    this.element.val(newValue).trigger('change');
17289                }
17290            }
17291        },
17292
17293        remove: function() {
17294            this.container.remove();
17295            this.element.off('.daterangepicker');
17296            this.element.removeData();
17297        }
17298
17299    };
17300
17301    $.fn.daterangepicker = function(options, callback) {
17302        var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options);
17303        this.each(function() {
17304            var el = $(this);
17305            if (el.data('daterangepicker'))
17306                el.data('daterangepicker').remove();
17307            el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback));
17308        });
17309        return this;
17310    };
17311
17312    return DateRangePicker;
17313
17314}));
17315
17316/*
17317 *  Bootstrap TouchSpin - v4.2.5
17318 *  A mobile and touch friendly input spinner component for Bootstrap 3 & 4.
17319 *  http://www.virtuosoft.eu/code/bootstrap-touchspin/
17320 *
17321 *  Made by István Ujj-Mészáros
17322 *  Under Apache License v2.0 License
17323 */
17324(function(factory) {
17325  if (typeof define === 'function' && define.amd) {
17326    define(['jquery'], factory);
17327  } else if (typeof module === 'object' && module.exports) {
17328    module.exports = function(root, jQuery) {
17329      if (jQuery === undefined) {
17330        if (typeof window !== 'undefined') {
17331          jQuery = require('jquery');
17332        }
17333        else {
17334          jQuery = require('jquery')(root);
17335        }
17336      }
17337      factory(jQuery);
17338      return jQuery;
17339    };
17340  } else {
17341    factory(jQuery);
17342  }
17343}(function($) {
17344  'use strict';
17345
17346  var _currentSpinnerId = 0;
17347
17348  $.fn.TouchSpin = function(options) {
17349
17350    var defaults = {
17351      min: 0, // If null, there is no minimum enforced
17352      max: 100, // If null, there is no maximum enforced
17353      initval: '',
17354      replacementval: '',
17355      step: 1,
17356      decimals: 0,
17357      stepinterval: 100,
17358      forcestepdivisibility: 'round', // none | floor | round | ceil
17359      stepintervaldelay: 500,
17360      verticalbuttons: false,
17361      verticalup: '+',
17362      verticaldown: '-',
17363      verticalupclass: '',
17364      verticaldownclass: '',
17365      prefix: '',
17366      postfix: '',
17367      prefix_extraclass: '',
17368      postfix_extraclass: '',
17369      booster: true,
17370      boostat: 10,
17371      maxboostedstep: false,
17372      mousewheel: true,
17373      buttondown_class: 'btn btn-primary',
17374      buttonup_class: 'btn btn-primary',
17375      buttondown_txt: '-',
17376      buttonup_txt: '+',
17377      callback_before_calculation: function(value) {
17378        return value;
17379      },
17380      callback_after_calculation: function(value) {
17381        return value;
17382      }
17383    };
17384
17385    var attributeMap = {
17386      min: 'min',
17387      max: 'max',
17388      initval: 'init-val',
17389      replacementval: 'replacement-val',
17390      step: 'step',
17391      decimals: 'decimals',
17392      stepinterval: 'step-interval',
17393      verticalbuttons: 'vertical-buttons',
17394      verticalupclass: 'vertical-up-class',
17395      verticaldownclass: 'vertical-down-class',
17396      forcestepdivisibility: 'force-step-divisibility',
17397      stepintervaldelay: 'step-interval-delay',
17398      prefix: 'prefix',
17399      postfix: 'postfix',
17400      prefix_extraclass: 'prefix-extra-class',
17401      postfix_extraclass: 'postfix-extra-class',
17402      booster: 'booster',
17403      boostat: 'boostat',
17404      maxboostedstep: 'max-boosted-step',
17405      mousewheel: 'mouse-wheel',
17406      buttondown_class: 'button-down-class',
17407      buttonup_class: 'button-up-class',
17408      buttondown_txt: 'button-down-txt',
17409      buttonup_txt: 'button-up-txt'
17410    };
17411
17412    return this.each(function() {
17413
17414      var settings,
17415        originalinput = $(this),
17416        originalinput_data = originalinput.data(),
17417        _detached_prefix,
17418        _detached_postfix,
17419        container,
17420        elements,
17421        value,
17422        downSpinTimer,
17423        upSpinTimer,
17424        downDelayTimeout,
17425        upDelayTimeout,
17426        spincount = 0,
17427        spinning = false;
17428
17429      init();
17430
17431      function init() {
17432        if (originalinput.data('alreadyinitialized')) {
17433          return;
17434        }
17435
17436        originalinput.data('alreadyinitialized', true);
17437        _currentSpinnerId += 1;
17438        originalinput.data('spinnerid', _currentSpinnerId);
17439
17440        if (!originalinput.is('input')) {
17441          console.log('Must be an input.');
17442          return;
17443        }
17444
17445        _initSettings();
17446        _setInitval();
17447        _checkValue();
17448        _buildHtml();
17449        _initElements();
17450        _hideEmptyPrefixPostfix();
17451        _bindEvents();
17452        _bindEventsInterface();
17453      }
17454
17455      function _setInitval() {
17456        if (settings.initval !== '' && originalinput.val() === '') {
17457          originalinput.val(settings.initval);
17458        }
17459      }
17460
17461      function changeSettings(newsettings) {
17462        _updateSettings(newsettings);
17463        _checkValue();
17464
17465        var value = elements.input.val();
17466
17467        if (value !== '') {
17468          value = Number(settings.callback_before_calculation(elements.input.val()));
17469          elements.input.val(settings.callback_after_calculation(Number(value).toFixed(settings.decimals)));
17470        }
17471      }
17472
17473      function _initSettings() {
17474        settings = $.extend({}, defaults, originalinput_data, _parseAttributes(), options);
17475      }
17476
17477      function _parseAttributes() {
17478        var data = {};
17479        $.each(attributeMap, function(key, value) {
17480          var attrName = 'bts-' + value + '';
17481          if (originalinput.is('[data-' + attrName + ']')) {
17482            data[key] = originalinput.data(attrName);
17483          }
17484        });
17485        return data;
17486      }
17487
17488      function _destroy() {
17489        var $parent = originalinput.parent();
17490
17491        stopSpin();
17492
17493        originalinput.off('.touchspin');
17494
17495        if ($parent.hasClass('bootstrap-touchspin-injected')) {
17496          originalinput.siblings().remove();
17497          originalinput.unwrap();
17498        }
17499        else {
17500          $('.bootstrap-touchspin-injected', $parent).remove();
17501          $parent.removeClass('bootstrap-touchspin');
17502        }
17503
17504        originalinput.data('alreadyinitialized', false);
17505      }
17506
17507      function _updateSettings(newsettings) {
17508        settings = $.extend({}, settings, newsettings);
17509
17510        // Update postfix and prefix texts if those settings were changed.
17511        if (newsettings.postfix) {
17512          var $postfix = originalinput.parent().find('.bootstrap-touchspin-postfix');
17513
17514          if ($postfix.length === 0) {
17515            _detached_postfix.insertAfter(originalinput);
17516          }
17517
17518          originalinput.parent().find('.bootstrap-touchspin-postfix .input-group-text').text(newsettings.postfix);
17519        }
17520
17521        if (newsettings.prefix) {
17522          var $prefix = originalinput.parent().find('.bootstrap-touchspin-prefix');
17523
17524          if ($prefix.length === 0) {
17525            _detached_prefix.insertBefore(originalinput);
17526          }
17527
17528          originalinput.parent().find('.bootstrap-touchspin-prefix .input-group-text').text(newsettings.prefix);
17529        }
17530
17531        _hideEmptyPrefixPostfix();
17532      }
17533
17534      function _buildHtml() {
17535        var initval = originalinput.val(),
17536          parentelement = originalinput.parent();
17537
17538        if (initval !== '') {
17539          initval = settings.callback_after_calculation(Number(initval).toFixed(settings.decimals));
17540        }
17541
17542        originalinput.data('initvalue', initval).val(initval);
17543        originalinput.addClass('form-control');
17544
17545        if (parentelement.hasClass('input-group')) {
17546          _advanceInputGroup(parentelement);
17547        }
17548        else {
17549          _buildInputGroup();
17550        }
17551      }
17552
17553      function _advanceInputGroup(parentelement) {
17554        parentelement.addClass('bootstrap-touchspin');
17555
17556        var prev = originalinput.prev(),
17557          next = originalinput.next();
17558
17559        var downhtml,
17560          uphtml,
17561          prefixhtml = '<span class="input-group-addon input-group-prepend bootstrap-touchspin-prefix input-group-prepend bootstrap-touchspin-injected"><span class="input-group-text">' + settings.prefix + '</span></span>',
17562          postfixhtml = '<span class="input-group-addon input-group-append bootstrap-touchspin-postfix input-group-append bootstrap-touchspin-injected"><span class="input-group-text">' + settings.postfix + '</span></span>';
17563
17564        if (prev.hasClass('input-group-btn') || prev.hasClass('input-group-prepend')) {
17565          downhtml = '<button class="' + settings.buttondown_class + ' bootstrap-touchspin-down bootstrap-touchspin-injected" type="button">' + settings.buttondown_txt + '</button>';
17566          prev.append(downhtml);
17567        }
17568        else {
17569          downhtml = '<span class="input-group-btn input-group-prepend bootstrap-touchspin-injected"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span>';
17570          $(downhtml).insertBefore(originalinput);
17571        }
17572
17573        if (next.hasClass('input-group-btn') || next.hasClass('input-group-append')) {
17574          uphtml = '<button class="' + settings.buttonup_class + ' bootstrap-touchspin-up bootstrap-touchspin-injected" type="button">' + settings.buttonup_txt + '</button>';
17575          next.prepend(uphtml);
17576        }
17577        else {
17578          uphtml = '<span class="input-group-btn input-group-append bootstrap-touchspin-injected"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span>';
17579          $(uphtml).insertAfter(originalinput);
17580        }
17581
17582        $(prefixhtml).insertBefore(originalinput);
17583        $(postfixhtml).insertAfter(originalinput);
17584
17585        container = parentelement;
17586      }
17587
17588      function _buildInputGroup() {
17589        var html;
17590
17591        var inputGroupSize = '';
17592        if (originalinput.hasClass('input-sm')) {
17593          inputGroupSize = 'input-group-sm';
17594        }
17595
17596        if (originalinput.hasClass('input-lg')) {
17597          inputGroupSize = 'input-group-lg';
17598        }
17599
17600        if (settings.verticalbuttons) {
17601          html = '<div class="input-group ' + inputGroupSize + ' bootstrap-touchspin bootstrap-touchspin-injected"><span class="input-group-addon input-group-prepend bootstrap-touchspin-prefix"><span class="input-group-text">' + settings.prefix + '</span></span><span class="input-group-addon bootstrap-touchspin-postfix input-group-append"><span class="input-group-text">' + settings.postfix + '</span></span><span class="input-group-btn-vertical"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-up ' + settings.verticalupclass + '" type="button">' + settings.verticalup + '</button><button class="' + settings.buttonup_class + ' bootstrap-touchspin-down ' + settings.verticaldownclass + '" type="button">' + settings.verticaldown + '</button></span></div>';
17602        }
17603        else {
17604          html = '<div class="input-group bootstrap-touchspin bootstrap-touchspin-injected"><span class="input-group-btn input-group-prepend"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span><span class="input-group-addon bootstrap-touchspin-prefix input-group-prepend"><span class="input-group-text">' + settings.prefix + '</span></span><span class="input-group-addon bootstrap-touchspin-postfix input-group-append"><span class="input-group-text">' + settings.postfix + '</span></span><span class="input-group-btn input-group-append"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span></div>';
17605        }
17606
17607        container = $(html).insertBefore(originalinput);
17608
17609        $('.bootstrap-touchspin-prefix', container).after(originalinput);
17610
17611        if (originalinput.hasClass('input-sm')) {
17612          container.addClass('input-group-sm');
17613        }
17614        else if (originalinput.hasClass('input-lg')) {
17615          container.addClass('input-group-lg');
17616        }
17617      }
17618
17619      function _initElements() {
17620        elements = {
17621          down: $('.bootstrap-touchspin-down', container),
17622          up: $('.bootstrap-touchspin-up', container),
17623          input: $('input', container),
17624          prefix: $('.bootstrap-touchspin-prefix', container).addClass(settings.prefix_extraclass),
17625          postfix: $('.bootstrap-touchspin-postfix', container).addClass(settings.postfix_extraclass)
17626        };
17627      }
17628
17629      function _hideEmptyPrefixPostfix() {
17630        if (settings.prefix === '') {
17631          _detached_prefix = elements.prefix.detach();
17632        }
17633
17634        if (settings.postfix === '') {
17635          _detached_postfix = elements.postfix.detach();
17636        }
17637      }
17638
17639      function _bindEvents() {
17640        originalinput.on('keydown.touchspin', function(ev) {
17641          var code = ev.keyCode || ev.which;
17642
17643          if (code === 38) {
17644            if (spinning !== 'up') {
17645              upOnce();
17646              startUpSpin();
17647            }
17648            ev.preventDefault();
17649          }
17650          else if (code === 40) {
17651            if (spinning !== 'down') {
17652              downOnce();
17653              startDownSpin();
17654            }
17655            ev.preventDefault();
17656          }
17657        });
17658
17659        originalinput.on('keyup.touchspin', function(ev) {
17660          var code = ev.keyCode || ev.which;
17661
17662          if (code === 38) {
17663            stopSpin();
17664          }
17665          else if (code === 40) {
17666            stopSpin();
17667          }
17668        });
17669
17670        originalinput.on('blur.touchspin', function() {
17671          _checkValue();
17672          originalinput.val(settings.callback_after_calculation(originalinput.val()));
17673        });
17674
17675        elements.down.on('keydown', function(ev) {
17676          var code = ev.keyCode || ev.which;
17677
17678          if (code === 32 || code === 13) {
17679            if (spinning !== 'down') {
17680              downOnce();
17681              startDownSpin();
17682            }
17683            ev.preventDefault();
17684          }
17685        });
17686
17687        elements.down.on('keyup.touchspin', function(ev) {
17688          var code = ev.keyCode || ev.which;
17689
17690          if (code === 32 || code === 13) {
17691            stopSpin();
17692          }
17693        });
17694
17695        elements.up.on('keydown.touchspin', function(ev) {
17696          var code = ev.keyCode || ev.which;
17697
17698          if (code === 32 || code === 13) {
17699            if (spinning !== 'up') {
17700              upOnce();
17701              startUpSpin();
17702            }
17703            ev.preventDefault();
17704          }
17705        });
17706
17707        elements.up.on('keyup.touchspin', function(ev) {
17708          var code = ev.keyCode || ev.which;
17709
17710          if (code === 32 || code === 13) {
17711            stopSpin();
17712          }
17713        });
17714
17715        elements.down.on('mousedown.touchspin', function(ev) {
17716          elements.down.off('touchstart.touchspin');  // android 4 workaround
17717
17718          if (originalinput.is(':disabled')) {
17719            return;
17720          }
17721
17722          downOnce();
17723          startDownSpin();
17724
17725          ev.preventDefault();
17726          ev.stopPropagation();
17727        });
17728
17729        elements.down.on('touchstart.touchspin', function(ev) {
17730          elements.down.off('mousedown.touchspin');  // android 4 workaround
17731
17732          if (originalinput.is(':disabled')) {
17733            return;
17734          }
17735
17736          downOnce();
17737          startDownSpin();
17738
17739          ev.preventDefault();
17740          ev.stopPropagation();
17741        });
17742
17743        elements.up.on('mousedown.touchspin', function(ev) {
17744          elements.up.off('touchstart.touchspin');  // android 4 workaround
17745
17746          if (originalinput.is(':disabled')) {
17747            return;
17748          }
17749
17750          upOnce();
17751          startUpSpin();
17752
17753          ev.preventDefault();
17754          ev.stopPropagation();
17755        });
17756
17757        elements.up.on('touchstart.touchspin', function(ev) {
17758          elements.up.off('mousedown.touchspin');  // android 4 workaround
17759
17760          if (originalinput.is(':disabled')) {
17761            return;
17762          }
17763
17764          upOnce();
17765          startUpSpin();
17766
17767          ev.preventDefault();
17768          ev.stopPropagation();
17769        });
17770
17771        elements.up.on('mouseup.touchspin mouseout.touchspin touchleave.touchspin touchend.touchspin touchcancel.touchspin', function(ev) {
17772          if (!spinning) {
17773            return;
17774          }
17775
17776          ev.stopPropagation();
17777          stopSpin();
17778        });
17779
17780        elements.down.on('mouseup.touchspin mouseout.touchspin touchleave.touchspin touchend.touchspin touchcancel.touchspin', function(ev) {
17781          if (!spinning) {
17782            return;
17783          }
17784
17785          ev.stopPropagation();
17786          stopSpin();
17787        });
17788
17789        elements.down.on('mousemove.touchspin touchmove.touchspin', function(ev) {
17790          if (!spinning) {
17791            return;
17792          }
17793
17794          ev.stopPropagation();
17795          ev.preventDefault();
17796        });
17797
17798        elements.up.on('mousemove.touchspin touchmove.touchspin', function(ev) {
17799          if (!spinning) {
17800            return;
17801          }
17802
17803          ev.stopPropagation();
17804          ev.preventDefault();
17805        });
17806
17807        originalinput.on('mousewheel.touchspin DOMMouseScroll.touchspin', function(ev) {
17808          if (!settings.mousewheel || !originalinput.is(':focus')) {
17809            return;
17810          }
17811
17812          var delta = ev.originalEvent.wheelDelta || -ev.originalEvent.deltaY || -ev.originalEvent.detail;
17813
17814          ev.stopPropagation();
17815          ev.preventDefault();
17816
17817          if (delta < 0) {
17818            downOnce();
17819          }
17820          else {
17821            upOnce();
17822          }
17823        });
17824      }
17825
17826      function _bindEventsInterface() {
17827        originalinput.on('touchspin.destroy', function() {
17828          _destroy();
17829        });
17830
17831        originalinput.on('touchspin.uponce', function() {
17832          stopSpin();
17833          upOnce();
17834        });
17835
17836        originalinput.on('touchspin.downonce', function() {
17837          stopSpin();
17838          downOnce();
17839        });
17840
17841        originalinput.on('touchspin.startupspin', function() {
17842          startUpSpin();
17843        });
17844
17845        originalinput.on('touchspin.startdownspin', function() {
17846          startDownSpin();
17847        });
17848
17849        originalinput.on('touchspin.stopspin', function() {
17850          stopSpin();
17851        });
17852
17853        originalinput.on('touchspin.updatesettings', function(e, newsettings) {
17854          changeSettings(newsettings);
17855        });
17856      }
17857
17858      function _forcestepdivisibility(value) {
17859        switch (settings.forcestepdivisibility) {
17860          case 'round':
17861            return (Math.round(value / settings.step) * settings.step).toFixed(setting
17861s.decimals);
17862          case 'floor':
17863            return (Math.floor(value / settings.step) * settings.step).toFixed(settings.decimals);
17864          case 'ceil':
17865            return (Math.ceil(value / settings.step) * settings.step).toFixed(settings.decimals);
17866          default:
17867            return value;
17868        }
17869      }
17870
17871      function _checkValue() {
17872        var val, parsedval, returnval;
17873
17874        val = settings.callback_before_calculation(originalinput.val());
17875
17876        if (val === '') {
17877          if (settings.replacementval !== '') {
17878            originalinput.val(settings.replacementval);
17879            originalinput.trigger('change');
17880          }
17881          return;
17882        }
17883
17884        if (settings.decimals > 0 && val === '.') {
17885          return;
17886        }
17887
17888        parsedval = parseFloat(val);
17889
17890        if (isNaN(parsedval)) {
17891          if (settings.replacementval !== '') {
17892            parsedval = settings.replacementval;
17893          }
17894          else {
17895            parsedval = 0;
17896          }
17897        }
17898
17899        returnval = parsedval;
17900
17901        if (parsedval.toString() !== val) {
17902          returnval = parsedval;
17903        }
17904
17905        if ((settings.min !== null) && (parsedval < settings.min)) {
17906          returnval = settings.min;
17907        }
17908
17909        if ((settings.max !== null) && (parsedval > settings.max)) {
17910          returnval = settings.max;
17911        }
17912
17913        returnval = _forcestepdivisibility(returnval);
17914
17915        if (Number(val).toString() !== returnval.toString()) {
17916          originalinput.val(returnval);
17917          originalinput.trigger('change');
17918        }
17919      }
17920
17921      function _getBoostedStep() {
17922        if (!settings.booster) {
17923          return settings.step;
17924        }
17925        else {
17926          var boosted = Math.pow(2, Math.floor(spincount / settings.boostat)) * settings.step;
17927
17928          if (settings.maxboostedstep) {
17929            if (boosted > settings.maxboostedstep) {
17930              boosted = settings.maxboostedstep;
17931              value = Math.round((value / boosted)) * boosted;
17932            }
17933          }
17934
17935          return Math.max(settings.step, boosted);
17936        }
17937      }
17938
17939      function upOnce() {
17940        _checkValue();
17941
17942        value = parseFloat(settings.callback_before_calculation(elements.input.val()));
17943        if (isNaN(value)) {
17944          value = 0;
17945        }
17946
17947        var initvalue = value,
17948          boostedstep = _getBoostedStep();
17949
17950        value = value + boostedstep;
17951
17952        if ((settings.max !== null) && (value > settings.max)) {
17953          value = settings.max;
17954          originalinput.trigger('touchspin.on.max');
17955          stopSpin();
17956        }
17957
17958        elements.input.val(settings.callback_after_calculation(Number(value).toFixed(settings.decimals)));
17959
17960        if (initvalue !== value) {
17961          originalinput.trigger('change');
17962        }
17963      }
17964
17965      function downOnce() {
17966        _checkValue();
17967
17968        value = parseFloat(settings.callback_before_calculation(elements.input.val()));
17969        if (isNaN(value)) {
17970          value = 0;
17971        }
17972
17973        var initvalue = value,
17974          boostedstep = _getBoostedStep();
17975
17976        value = value - boostedstep;
17977
17978        if ((settings.min !== null) && (value < settings.min)) {
17979          value = settings.min;
17980          originalinput.trigger('touchspin.on.min');
17981          stopSpin();
17982        }
17983
17984        elements.input.val(settings.callback_after_calculation(Number(value).toFixed(settings.decimals)));
17985
17986        if (initvalue !== value) {
17987          originalinput.trigger('change');
17988        }
17989      }
17990
17991      function startDownSpin() {
17992        stopSpin();
17993
17994        spincount = 0;
17995        spinning = 'down';
17996
17997        originalinput.trigger('touchspin.on.startspin');
17998        originalinput.trigger('touchspin.on.startdownspin');
17999
18000        downDelayTimeout = setTimeout(function() {
18001          downSpinTimer = setInterval(function() {
18002            spincount++;
18003            downOnce();
18004          }, settings.stepinterval);
18005        }, settings.stepintervaldelay);
18006      }
18007
18008      function startUpSpin() {
18009        stopSpin();
18010
18011        spincount = 0;
18012        spinning = 'up';
18013
18014        originalinput.trigger('touchspin.on.startspin');
18015        originalinput.trigger('touchspin.on.startupspin');
18016
18017        upDelayTimeout = setTimeout(function() {
18018          upSpinTimer = setInterval(function() {
18019            spincount++;
18020            upOnce();
18021          }, settings.stepinterval);
18022        }, settings.stepintervaldelay);
18023      }
18024
18025      function stopSpin() {
18026        clearTimeout(downDelayTimeout);
18027        clearTimeout(upDelayTimeout);
18028        clearInterval(downSpinTimer);
18029        clearInterval(upSpinTimer);
18030
18031        switch (spinning) {
18032          case 'up':
18033            originalinput.trigger('touchspin.on.stopupspin');
18034            originalinput.trigger('touchspin.on.stopspin');
18035            break;
18036          case 'down':
18037            originalinput.trigger('touchspin.on.stopdownspin');
18038            originalinput.trigger('touchspin.on.stopspin');
18039            break;
18040        }
18041
18042        spincount = 0;
18043        spinning = false;
18044      }
18045
18046    });
18047
18048  };
18049
18050}));
18051
18052(function ($) {
18053  'use strict';
18054  /**
18055   * We need an event when the elements are destroyed
18056   * because if an input is removed, we have to remove the
18057   * maxlength object associated (if any).
18058   * From:
18059   * http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
18060   */
18061  if (!$.event.special.destroyed) {
18062    $.event.special.destroyed = {
18063      remove: function (o) {
18064        if (o.handler) {
18065          o.handler();
18066        }
18067      }
18068    };
18069  }
18070
18071
18072  $.fn.extend({
18073    maxlength: function (options, callback) {
18074      var documentBody = $('body'),
18075        defaults = {
18076          showOnReady: false, // true to always show when indicator is ready
18077          alwaysShow: false, // if true the indicator it's always shown.
18078          threshold: 10, // Represents how many chars left are needed to show up the counter
18079          warningClass: 'label label-success',
18080          limitReachedClass: 'label label-important label-danger',
18081          separator: ' / ',
18082          preText: '',
18083          postText: '',
18084          showMaxLength: true,
18085          placement: 'bottom',
18086          message: null, // an alternative way to provide the message text
18087          showCharsTyped: true, // show the number of characters typed and not the number of characters remaining
18088          validate: false, // if the browser doesn't support the maxlength attribute, attempt to type more than
18089          // the indicated chars, will be prevented.
18090          utf8: false, // counts using bytesize rather than length. eg: '£' is counted as 2 characters.
18091          appendToParent: false, // append the indicator to the input field's parent instead of body
18092          twoCharLinebreak: true,  // count linebreak as 2 characters to match IE/Chrome textarea validation. As well as DB storage.
18093          allowOverMax: false  // false = use maxlength attribute and browswer functionality.
18094          // true = removes maxlength attribute and replaces with 'data-bs-mxl'.
18095          // Form submit validation is handled on your own.  when maxlength has been exceeded 'overmax' class added to element
18096        };
18097
18098      if ($.isFunction(options) && !callback) {
18099        callback = options;
18100        options = {};
18101      }
18102      options = $.extend(defaults, options);
18103
18104      /**
18105      * Return the length of the specified input.
18106      *
18107      * @param input
18108      * @return {number}
18109      */
18110      function inputLength(input) {
18111        var text = input.val();
18112
18113        if (options.twoCharLinebreak) {
18114          // Count all line breaks as 2 characters
18115          text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
18116        } else {
18117          // Remove all double-character (\r\n) linebreaks, so they're counted only once.
18118          text = text.replace(new RegExp('\r?\n', 'g'), '\n');
18119        }
18120
18121        var currentLength = 0;
18122
18123        if (options.utf8) {
18124          currentLength = utf8Length(text);
18125        } else {
18126          currentLength = text.length;
18127        }
18128        return currentLength;
18129      }
18130
18131      /**
18132      * Truncate the text of the specified input.
18133      *
18134      * @param input
18135      * @param limit
18136      */
18137      function truncateChars(input, maxlength) {
18138        var text = input.val();
18139        var newlines = 0;
18140
18141        if (options.twoCharLinebreak) {
18142          text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
18143
18144          if (text.substr(text.length - 1) === '\n' && text.length % 2 === 1) {
18145            newlines = 1;
18146          }
18147        }
18148
18149        input.val(text.substr(0, maxlength - newlines));
18150      }
18151
18152      /**
18153      * Return the length of the specified input in UTF8 encoding.
18154      *
18155      * @param input
18156      * @return {number}
18157      */
18158      function utf8Length(string) {
18159        var utf8length = 0;
18160        for (var n = 0; n < string.length; n++) {
18161          var c = string.charCodeAt(n);
18162          if (c < 128) {
18163            utf8length++;
18164          }
18165          else if ((c > 127) && (c < 2048)) {
18166            utf8length = utf8length + 2;
18167          }
18168          else {
18169            utf8length = utf8length + 3;
18170          }
18171        }
18172        return utf8length;
18173      }
18174
18175      /**
18176       * Return true if the indicator should be showing up.
18177       *
18178       * @param input
18179       * @param thereshold
18180       * @param maxlength
18181       * @return {number}
18182       */
18183      function charsLeftThreshold(input, thereshold, maxlength) {
18184        var output = true;
18185        if (!options.alwaysShow && (maxlength - inputLength(input) > thereshold)) {
18186          output = false;
18187        }
18188        return output;
18189      }
18190
18191      /**
18192       * Returns how many chars are left to complete the fill up of the form.
18193       *
18194       * @param input
18195       * @param maxlength
18196       * @return {number}
18197       */
18198      function remainingChars(input, maxlength) {
18199        var length = maxlength - inputLength(input);
18200        return length;
18201      }
18202
18203      /**
18204       * When called displays the indicator.
18205       *
18206       * @param indicator
18207       */
18208      function showRemaining(currentInput, indicator) {
18209        indicator.css({
18210          display: 'block'
18211        });
18212        currentInput.trigger('maxlength.shown');
18213      }
18214
18215      /**
18216       * When called shows the indicator.
18217       *
18218       * @param indicator
18219       */
18220      function hideRemaining(currentInput, indicator) {
18221        indicator.css({
18222          display: 'none'
18223        });
18224        currentInput.trigger('maxlength.hidden');
18225      }
18226
18227      /**
18228      * This function updates the value in the indicator
18229      *
18230      * @param maxLengthThisInput
18231      * @param typedChars
18232      * @return String
18233      */
18234      function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) {
18235        var output = '';
18236        if (options.message) {
18237          if (typeof options.message === 'function') {
18238            output = options.message(currentInputText, maxLengthThisInput);
18239          } else {
18240            output = options.message.replace('%charsTyped%', typedChars)
18241              .replace('%charsRemaining%', maxLengthThisInput - typedChars)
18242              .replace('%charsTotal%', maxLengthThisInput);
18243          }
18244        } else {
18245          if (options.preText) {
18246            output += options.preText;
18247          }
18248          if (!options.showCharsTyped) {
18249            output += maxLengthThisInput - typedChars;
18250          }
18251          else {
18252            output += typedChars;
18253          }
18254          if (options.showMaxLength) {
18255            output += options.separator + maxLengthThisInput;
18256          }
18257          if (options.postText) {
18258            output += options.postText;
18259          }
18260        }
18261        return output;
18262      }
18263
18264      /**
18265       * This function updates the value of the counter in the indicator.
18266       * Wants as parameters: the number of remaining chars, the element currently managed,
18267       * the maxLength for the current input and the indicator generated for it.
18268       *
18269       * @param remaining
18270       * @param currentInput
18271       * @param maxLengthCurrentInput
18272       * @param maxLengthIndicator
18273       */
18274      function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) {
18275        if (maxLengthIndicator) {
18276          maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, (maxLengthCurrentInput - remaining)));
18277
18278          if (remaining > 0) {
18279            if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) {
18280              showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass).addClass(options.warningClass));
18281            } else {
18282              hideRemaining(currentInput, maxLengthIndicator);
18283            }
18284          } else {
18285            showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass));
18286          }
18287        }
18288
18289        if (options.allowOverMax) {
18290          // class to use for form validation on custom maxlength attribute
18291          if (remaining < 0) {
18292            currentInput.addClass('overmax');
18293          } else {
18294            currentInput.removeClass('overmax');
18295          }
18296        }
18297      }
18298
18299      /**
18300       * This function returns an object containing all the
18301       * informations about the position of the current input
18302       *
18303       * @param currentInput
18304       * @return object {bottom height left right top width}
18305       *
18306       */
18307      function getPosition(currentInput) {
18308        var el = currentInput[0];
18309        return $.extend({}, (typeof el.getBoundingClientRect === 'function') ? el.getBoundingClientRect() : {
18310          width: el.offsetWidth,
18311          height: el.offsetHeight
18312        }, currentInput.offset());
18313      }
18314
18315      /**
18316       * This function places the maxLengthIndicator at the
18317       * top / bottom / left / right of the currentInput
18318       *
18319       * @param currentInput
18320       * @param maxLengthIndicator
18321       * @return null
18322       *
18323       */
18324      function place(currentInput, maxLengthIndicator) {
18325        var pos = getPosition(currentInput);
18326
18327        // Supports custom placement handler
18328        if ($.type(options.placement) === 'function'){
18329          options.placement(currentInput, maxLengthIndicator, pos);
18330          return;
18331        }
18332
18333        // Supports custom placement via css positional properties
18334        if ($.isPlainObject(options.placement)){
18335          placeWithCSS(options.placement, maxLengthIndicator);
18336          return;
18337        }
18338
18339        var inputOuter = currentInput.outerWidth(),
18340          outerWidth = maxLengthIndicator.outerWidth(),
18341          actualWidth = maxLengthIndicator.width(),
18342          actualHeight = maxLengthIndicator.height();
18343
18344        // get the right position if the indicator is appended to the input's parent
18345        if (options.appendToParent) {
18346          pos.top -= currentInput.parent().offset().top;
18347          pos.left -= currentInput.parent().offset().left;
18348        }
18349
18350        switch (options.placement) {
18351          case 'bottom':
18352            maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 });
18353            break;
18354          case 'top':
18355            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 });
18356            break;
18357          case 'left':
18358            maxLengthIndicator.css({ top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth });
18359            break;
18360          case 'right':
18361            maxLengthIndicator.css({ top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width });
18362            break;
18363          case 'bottom-right':
18364            maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width });
18365            break;
18366          case 'top-right':
18367            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + inputOuter });
18368            break;
18369          case 'top-left':
18370            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left - outerWidth });
18371            break;
18372          case 'bottom-left':
18373            maxLengthIndicator.css({ top: pos.top + currentInput.outerHeight(), left: pos.left - outerWidth });
18374            break;
18375          case 'centered-right':
18376            maxLengthIndicator.css({ top: pos.top + (actualHeight / 2), left: pos.left + inputOuter - outerWidth - 3 });
18377            break;
18378
18379            // Some more options for placements
18380          case 'bottom-right-inside':
18381            maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width - outerWidth });
18382            break;
18383          case 'top-right-inside':
18384            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + inputOuter - outerWidth });
18385            break;
18386          case 'top-left-inside':
18387            maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left });
18388            break;
18389          case 'bottom-left-inside':
18390            maxLengthIndicator.css({ top: pos.top + currentInput.outerHeight(), left: pos.left });
18391            break;
18392        }
18393      }
18394
18395      /**
18396       * This function places the maxLengthIndicator based on placement config object.
18397       *
18398       * @param {object} placement
18399       * @param {$} maxLengthIndicator
18400       * @return null
18401       *
18402       */
18403      function placeWithCSS(placement, maxLengthIndicator) {
18404        if (!placement || !maxLengthIndicator){
18405          return;
18406        }
18407
18408        var POSITION_KEYS = [
18409          'top',
18410          'bottom',
18411          'left',
18412          'right',
18413          'position'
18414        ];
18415
18416        var cssPos = {};
18417
18418        // filter css properties to position
18419        $.each(POSITION_KEYS, function (i, key) {
18420          var val = options.placement[key];
18421          if (typeof val !== 'undefined'){
18422            cssPos[key] = val;
18423          }
18424        });
18425
18426        maxLengthIndicator.css(cssPos);
18427
18428        return;
18429      }
18430
18431      /**
18432       * This function retrieves the maximum length of currentInput
18433       *
18434       * @param currentInput
18435       * @return {number}
18436       *
18437       */
18438      function getMaxLength(currentInput) {
18439        var attr = 'maxlength';
18440        if (options.allowOverMax) {
18441          attr = 'data-bs-mxl';
18442        }
18443        return currentInput.attr(attr) || currentInput.attr('size');
18444      }
18445
18446      return this.each(function () {
18447
18448        var currentInput = $(this),
18449          maxLengthCurrentInput,
18450          maxLengthIndicator;
18451
18452        $(window).resize(function () {
18453          if (maxLengthIndicator) {
18454            place(currentInput, maxLengthIndicator);
18455          }
18456        });
18457
18458        if (options.allowOverMax) {
18459          $(this).attr('data-bs-mxl', $(this).attr('maxlength'));
18460          $(this).removeAttr('maxlength');
18461        }
18462
18463        function firstInit() {
18464          var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, '0');
18465          maxLengthCurrentInput = getMaxLength(currentInput);
18466
18467          if (!maxLengthIndicator) {
18468            maxLengthIndicator = $('<span class="bootstrap-maxlength"></span>').css({
18469              display: 'none',
18470              position: 'absolute',
18471              whiteSpace: 'nowrap',
18472              zIndex: 1099
18473            }).html(maxlengthContent);
18474          }
18475
18476          // We need to detect resizes if we are dealing with a textarea:
18477          if (currentInput.is('textarea')) {
18478            currentInput.data('maxlenghtsizex', currentInput.outerWidth());
18479            currentInput.data('maxlenghtsizey', currentInput.outerHeight());
18480
18481            currentInput.mouseup(function () {
18482              if (currentInput.outerWidth() !== currentInput.data('maxlenghtsizex') || currentInput.outerHeight() !== currentInput.data('maxlenghtsizey')) {
18483                place(currentInput, maxLengthIndicator);
18484              }
18485
18486              currentInput.data('maxlenghtsizex', currentInput.outerWidth());
18487              currentInput.data('maxlenghtsizey', currentInput.outerHeight());
18488            });
18489          }
18490
18491          if (options.appendToParent) {
18492            currentInput.parent().append(maxLengthIndicator);
18493            currentInput.parent().css('position', 'relative');
18494          } else {
18495            documentBody.append(maxLengthIndicator);
18496          }
18497
18498          var remaining = remainingChars(currentInput, getMaxLength(currentInput));
18499          manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
18500          place(currentInput, maxLengthIndicator);
18501        }
18502
18503        if (options.showOnReady) {
18504          currentInput.ready(function () {
18505            firstInit();
18506          });
18507        } else {
18508          currentInput.focus(function () {
18509            firstInit();
18510          });
18511        }
18512
18513        currentInput.on('maxlength.reposition', function () {
18514          place(currentInput, maxLengthIndicator);
18515        });
18516
18517
18518        currentInput.on('destroyed', function () {
18519          if (maxLengthIndicator) {
18520            maxLengthIndicator.remove();
18521          }
18522        });
18523
18524        currentInput.on('blur', function () {
18525          if (maxLengthIndicator && !options.showOnReady) {
18526            maxLengthIndicator.remove();
18527          }
18528        });
18529
18530        currentInput.on('input', function () {
18531          var maxlength = getMaxLength(currentInput),
18532            remaining = remainingChars(currentInput, maxlength),
18533            output = true;
18534
18535          if (options.validate && remaining < 0) {
18536            truncateChars(currentInput, maxlength);
18537            output = false;
18538          } else {
18539            manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
18540          }
18541
18542          //reposition the indicator if placement "bottom-right-inside" & "top-right-inside" is used
18543          if (options.placement === 'bottom-right-inside' || options.placement === 'top-right-inside') {
18544            place(currentInput, maxLengthIndicator);
18545          }
18546
18547          return output;
18548        });
18549      });
18550    }
18551  });
18552}(jQuery));
18553
18554+function(a){"use strict";function c(c){return this.each(function(){var d=a(this),e=d.data("multiselectsplitter"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("multiselectsplitter",e=new b(this,f)),"string"==typeof c&&e[c]())})}var b=function(a,b){this.init("multiselectsplitter",a,b)};b.DEFAULTS={selectSize:null,maxSelectSize:null,clearOnFirstChange:!1,onlySameGroup:!1,groupCounter:!1,maximumSelected:null,afterInitialize:null,maximumAlert:function(a){alert("Only "+a+" values can be selected")},createFirstSelect:function(a,b){return"<option>"+a+"</option>"},createSecondSelect:function(a,b){return"<option>"+a+"</option>"},template:'<div class="row" data-multiselectsplitter-wrapper-selector><div class="col-xs-6 col-sm-6"><select class="form-control" data-multiselectsplitter-firstselect-selector></select></div> <!-- Add the extra clearfix for only the required viewport --><div class="col-xs-6 col-sm-6"><select class="form-control" data-multiselectsplitter-secondselect-selector></select></div></div>'},b.prototype.init=function(c,d,e){var f=this;f.type=c,f.last$ElementSelected=[],f.initialized=!1,f.$element=a(d),f.$element.hide(),f.options=a.extend({},b.DEFAULTS,e),f.$element.after(f.options.template),f.$wrapper=f.$element.next("div[data-multiselectsplitter-wrapper-selector]"),f.$firstSelect=a("select[data-multiselectsplitter-firstselect-selector]",f.$wrapper),f.$secondSelect=a("select[data-multiselectsplitter-secondselect-selector]",f.$wrapper);var g=0,h=0;if(0!=f.$element.find("optgroup").length){f.$element.find("optgroup").each(function(){var b=a(this).attr("label"),c=a(f.options.createFirstSelect(b,f.$element));c.val(b),c.attr("data-current-label",c.text()),f.$firstSelect.append(c);var d=a(this).find("option").length;d>h&&(h=d),g++});var i=Math.max(g,h);i=Math.min(i,10),f.options.selectSize?i=f.options.selectSize:f.options.maxSelectSize&&(i=Math.min(i,f.options.maxSelectSize)),f.$firstSelect.attr("size",i),f.$secondSelect.attr("size",i),f.$element.attr("multiple")&&f.$secondSelect.attr("multiple","multiple"),f.$element.is(":disabled")&&f.disable(),f.$firstSelect.on("change",a.proxy(f.updateParentCategory,f)),f.$secondSelect.on("click change",a.proxy(f.updateChildCategory,f)),f.update=function(){if(!(f.$element.find("option").length<1)){var b,a=f.$element.find("option:selected:first");b=a.length?a.parent().attr("label"):f.$element.find("option:first").parent().attr("label"),f.$firstSelect.find('option[value="'+b+'"]').prop("selected",!0),f.$firstSelect.trigger("change")}}
18554,f.update(),f.initialized=!0,f.options.afterInitialize&&f.options.afterInitialize(f.$firstSelect,f.$secondSelect)}},b.prototype.disable=function(){this.$secondSelect.prop("disabled",!0),this.$firstSelect.prop("disabled",!0)},b.prototype.enable=function(){this.$secondSelect.prop("disabled",!1),this.$firstSelect.prop("disabled",!1)},b.prototype.createSecondSelect=function(){var b=this;b.$secondSelect.empty(),a.each(b.$element.find('optgroup[label="'+b.$firstSelect.val()+'"] option'),function(c,d){var e=a(this).val(),f=a(this).text(),g=a(b.options.createSecondSelect(f,b.$firstSelect));g.val(e),a.each(b.$element.find("option:selected"),function(b,c){a(c).val()==e&&g.prop("selected",!0)}),b.$secondSelect.append(g)})},b.prototype.updateParentCategory=function(){var a=this;a.last$ElementSelected=a.$element.find("option:selected"),a.options.clearOnFirstChange&&a.initialized&&a.$element.find("option:selected").prop("selected",!1),a.createSecondSelect(),a.checkSelected(),a.updateCounter()},b.prototype.updateCounter=function(){var b=this;b.$element.attr("multiple")&&b.options.groupCounter&&a.each(b.$firstSelect.find("option"),function(c,d){var e=a(d).val(),f=a(d).data("currentLabel"),g=b.$element.find('optgroup[label="'+e+'"] option:selected').length;g>0&&(f+=" ("+g+")"),a(d).html(f)})},b.prototype.checkSelected=function(){var b=this;if(b.$element.attr("multiple")&&b.options.maximumSelected){var c=0;if(c="function"==typeof b.options.maximumSelected?b.options.maximumSelected(b.$firstSelect,b.$secondSelect):b.options.maximumSelected,!(c<1)){var d=b.$element.find("option:selected");if(d.length>c){b.$firstSelect.find("option:selected").prop("selected",!1),b.$secondSelect.find("option:selected").prop("selected",!1),b.initialized?(b.$element.find("option:selected").prop("selected",!1),b.last$ElementSelected.prop("selected",!0)):a.each(b.$element.find("option:selected"),function(b,d){b>c-1&&a(d).prop("selected",!1)});var e=b.last$ElementSelected.first().parent().attr("label");b.$firstSelect.find('option[value="'+e+'"]').prop("selected",!0),b.createSecondSelect(),b.options.maximumAlert(c)}}}},b.prototype.basicUpdateChildCategory=function(b,c){var d=this;d.last$ElementSelected=d.$element.find("option:selected");var e=d.$secondSelect.val();a.isArray(e)||(e=[e]);var f=d.$firstSelect.val(),g=!1;d.$element.attr("multiple")?d.options.onlySameGroup?a.each(d.$element.find("option:selected"),function(b,c){if(a(c).parent().attr("label")!=f)return g=!0,!1}):c||(g=!0):g=!0,g?d.$element.find("option:selected").prop("selected",!1):a.each(d.$element.find("option:selected"),function(b,c){f==a(c).parent().attr("label")&&a.inArray(a(c).val(),e)==-1&&a(c).prop("selected",!1)}),a.each(e,function(a,b){d.$element.find('option[value="'+b+'"]').prop("selected",!0)}),d.checkSelected(),d.updateCounter(),d.$element.trigger("change")},b.prototype.updateChildCategory=function(b){"change"==b.type?this.timeOut=setTimeout(a.proxy(function(){this.basicUpdateChildCategory(b,b.ctrlKey)},this),10):"click"==b.type&&(clearTimeout(this.timeOut),this.basicUpdateChildCategory(b,b.ctrlKey))},b.prototype.destroy=function(){this.$wrapper.remove(),this.$element.removeData(this.type),this.$element.show()},a.fn.multiselectsplitter=c,a.fn.multiselectsplitter.Constructor=b,a.fn.multiselectsplitter.VERSION="1.0.1"}(jQuery);
18555/*!
18556 * Bootstrap-select v1.13.5 (https://developer.snapappointments.com/bootstrap-select)
18557 *
18558 * Copyright 2012-2018 SnapAppointments, LLC
18559 * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
18560 */
18561
18562(function (root, factory) {
18563  if (root === undefined && window !== undefined) root = window;
18564  if (typeof define === 'function' && define.amd) {
18565    // AMD. Register as an anonymous module unless amdModuleId is set
18566    define(["jquery"], function (a0) {
18567      return (factory(a0));
18568    });
18569  } else if (typeof module === 'object' && module.exports) {
18570    // Node. Does not work with strict CommonJS, but
18571    // only CommonJS-like environments that support module.exports,
18572    // like Node.
18573    module.exports = factory(require("jquery"));
18574  } else {
18575    factory(root["jQuery"]);
18576  }
18577}(this, function (jQuery) {
18578
18579(function ($) {
18580  'use strict';
18581
18582  // Polyfill for browsers with no classList support
18583  // Remove in v2
18584  if (!('classList' in document.createElement('_'))) {
18585    (function (view) {
18586      if (!('Element' in view)) return;
18587
18588      var classListProp = 'classList',
18589          protoProp = 'prototype',
18590          elemCtrProto = view.Element[protoProp],
18591          objCtr = Object,
18592          classListGetter = function () {
18593            var $elem = $(this);
18594
18595            return {
18596              add: function (classes) {
vendor: 13,858 bytes, lines 18597-19045
18597                return $elem.addClass(classes);
18598              },
18599              remove: function (classes) {
18600                return $elem.removeClass(classes);
18601              },
18602              toggle: function (classes, force) {
18603                return $elem.toggleClass(classes, force);
18604              },
18605              contains: function (classes) {
18606                return $elem.hasClass(classes);
18607              }
18608            }
18609          };
18610
18611      if (objCtr.defineProperty) {
18612        var classListPropDesc = {
18613          get: classListGetter,
18614          enumerable: true,
18615          configurable: true
18616        };
18617        try {
18618          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
18619        } catch (ex) { // IE 8 doesn't support enumerable:true
18620          // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36
18621          // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected
18622          if (ex.number === undefined || ex.number === -0x7FF5EC54) {
18623            classListPropDesc.enumerable = false;
18624            objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
18625          }
18626        }
18627      } else if (objCtr[protoProp].__defineGetter__) {
18628        elemCtrProto.__defineGetter__(classListProp, classListGetter);
18629      }
18630    }(window));
18631  }
18632
18633  var testElement = document.createElement('_');
18634
18635  testElement.classList.toggle('c3', false);
18636
18637  // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
18638  // support the second argument.
18639  if (testElement.classList.contains('c3')) {
18640    var _toggle = DOMTokenList.prototype.toggle;
18641
18642    DOMTokenList.prototype.toggle = function (token, force) {
18643      if (1 in arguments && !this.contains(token) === !force) {
18644        return force;
18645      } else {
18646        return _toggle.call(this, token);
18647      }
18648    };
18649  }
18650
18651  testElement = null;
18652
18653  // shallow array comparison
18654  function isEqual (array1, array2) {
18655    return array1.length === array2.length && array1.every(function (element, index) {
18656      return element === array2[index];
18657    });
18658  };
18659
18660  // <editor-fold desc="Shims">
18661  if (!String.prototype.startsWith) {
18662    (function () {
18663      'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
18664      var defineProperty = (function () {
18665        // IE 8 only supports `Object.defineProperty` on DOM elements
18666        try {
18667          var object = {};
18668          var $defineProperty = Object.defineProperty;
18669          var result = $defineProperty(object, object, object) && $defineProperty;
18670        } catch (error) {
18671        }
18672        return result;
18673      }());
18674      var toString = {}.toString;
18675      var startsWith = function (search) {
18676        if (this == null) {
18677          throw new TypeError();
18678        }
18679        var string = String(this);
18680        if (search && toString.call(search) == '[object RegExp]') {
18681          throw new TypeError();
18682        }
18683        var stringLength = string.length;
18684        var searchString = String(search);
18685        var searchLength = searchString.length;
18686        var position = arguments.length > 1 ? arguments[1] : undefined;
18687        // `ToInteger`
18688        var pos = position ? Number(position) : 0;
18689        if (pos != pos) { // better `isNaN`
18690          pos = 0;
18691        }
18692        var start = Math.min(Math.max(pos, 0), stringLength);
18693        // Avoid the `indexOf` call if no match is possible
18694        if (searchLength + start > stringLength) {
18695          return false;
18696        }
18697        var index = -1;
18698        while (++index < searchLength) {
18699          if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
18700            return false;
18701          }
18702        }
18703        return true;
18704      };
18705      if (defineProperty) {
18706        defineProperty(String.prototype, 'startsWith', {
18707          'value': startsWith,
18708          'configurable': true,
18709          'writable': true
18710        });
18711      } else {
18712        String.prototype.startsWith = startsWith;
18713      }
18714    }());
18715  }
18716
18717  if (!Object.keys) {
18718    Object.keys = function (
18719      o, // object
18720      k, // key
18721      r  // result array
18722    ) {
18723      // initialize object and result
18724      r = [];
18725      // iterate over object keys
18726      for (k in o) {
18727        // fill result array with non-prototypical keys
18728        r.hasOwnProperty.call(o, k) && r.push(k);
18729      }
18730      // return result
18731      return r;
18732    };
18733  }
18734
18735  // much faster than $.val()
18736  function getSelectValues (select) {
18737    var result = [];
18738    var options = select && select.options;
18739    var opt;
18740
18741    if (select.multiple) {
18742      for (var i = 0, len = options.length; i < len; i++) {
18743        opt = options[i];
18744
18745        if (opt.selected) {
18746          result.push(opt.value || opt.text);
18747        }
18748      }
18749    } else {
18750      result = select.value;
18751    }
18752
18753    return result;
18754  }
18755
18756  // set data-selected on select element if the value has been programmatically selected
18757  // prior to initialization of bootstrap-select
18758  // * consider removing or replacing an alternative method *
18759  var valHooks = {
18760    useDefault: false,
18761    _set: $.valHooks.select.set
18762  };
18763
18764  $.valHooks.select.set = function (elem, value) {
18765    if (value && !valHooks.useDefault) $(elem).data('selected', true);
18766
18767    return valHooks._set.apply(this, arguments);
18768  };
18769
18770  var changedArguments = null;
18771
18772  var EventIsSupported = (function () {
18773    try {
18774      new Event('change');
18775      return true;
18776    } catch (e) {
18777      return false;
18778    }
18779  })();
18780
18781  $.fn.triggerNative = function (eventName) {
18782    var el = this[0],
18783        event;
18784
18785    if (el.dispatchEvent) { // for modern browsers & IE9+
18786      if (EventIsSupported) {
18787        // For modern browsers
18788        event = new Event(eventName, {
18789          bubbles: true
18790        });
18791      } else {
18792        // For IE since it doesn't support Event constructor
18793        event = document.createEvent('Event');
18794        event.initEvent(eventName, true, false);
18795      }
18796
18797      el.dispatchEvent(event);
18798    } else if (el.fireEvent) { // for IE8
18799      event = document.createEventObject();
18800      event.eventType = eventName;
18801      el.fireEvent('on' + eventName, event);
18802    } else {
18803      // fall back to jQuery.trigger
18804      this.trigger(eventName);
18805    }
18806  };
18807  // </editor-fold>
18808
18809  function stringSearch (li, searchString, method, normalize) {
18810    var stringTypes = [
18811          'content',
18812          'subtext',
18813          'tokens'
18814        ],
18815        searchSuccess = false;
18816
18817    for (var i = 0; i < stringTypes.length; i++) {
18818      var stringType = stringTypes[i],
18819          string = li[stringType];
18820
18821      if (string) {
18822        string = string.toString();
18823
18824        // Strip HTML tags. This isn't perfect, but it's much faster than any other method
18825        if (stringType === 'content') {
18826          string = string.replace(/<[^>]+>/g, '');
18827        }
18828
18829        if (normalize) string = normalizeToBase(string);
18830        string = string.toUpperCase();
18831
18832        if (method === 'contains') {
18833          searchSuccess = string.indexOf(searchString) >= 0;
18834        } else {
18835          searchSuccess = string.startsWith(searchString);
18836        }
18837
18838        if (searchSuccess) break;
18839      }
18840    }
18841
18842    return searchSuccess;
18843  }
18844
18845  function toInteger (value) {
18846    return parseInt(value, 10) || 0;
18847  }
18848
18849  // Borrowed from Lodash (_.deburr)
18850  /** Used to map Latin Unicode letters to basic Latin letters. */
18851  var deburredLetters = {
18852    // Latin-1 Supplement block.
18853    '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
18854    '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
18855    '\xc7': 'C',  '\xe7': 'c',
18856    '\xd0': 'D',  '\xf0': 'd',
18857    '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
18858    '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
18859    '\xcc': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
18860    '\xec': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
18861    '\xd1': 'N',  '\xf1': 'n',
18862    '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
18863    '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
18864    '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
18865    '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
18866    '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
18867    '\xc6': 'Ae', '\xe6': 'ae',
18868    '\xde': 'Th', '\xfe': 'th',
18869    '\xdf': 'ss',
18870    // Latin Extended-A block.
18871    '\u0100': 'A',  '\u0102': 'A', '\u0104': 'A',
18872    '\u0101': 'a',  '\u0103': 'a', '\u0105': 'a',
18873    '\u0106': 'C',  '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
18874    '\u0107': 'c',  '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
18875    '\u010e': 'D',  '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
18876    '\u0112': 'E',  '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
18877    '\u0113': 'e',  '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
18878    '\u011c': 'G',  '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
18879    '\u011d': 'g',  '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
18880    '\u0124': 'H',  '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
18881    '\u0128': 'I',  '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
18882    '\u0129': 'i',  '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
18883    '\u0134': 'J',  '\u0135': 'j',
18884    '\u0136': 'K',  '\u0137': 'k', '\u0138': 'k',
18885    '\u0139': 'L',  '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
18886    '\u013a': 'l',  '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
18887    '\u0143': 'N',  '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
18888    '\u0144': 'n',  '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
18889    '\u014c': 'O',  '\u014e': 'O', '\u0150': 'O',
18890    '\u014d': 'o',  '\u014f': 'o', '\u0151': 'o',
18891    '\u0154': 'R',  '\u0156': 'R', '\u0158': 'R',
18892    '\u0155': 'r',  '\u0157': 'r', '\u0159': 'r',
18893    '\u015a': 'S',  '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
18894    '\u015b': 's',  '\u015d': 's', '\u015f': 's', '\u0161': 's',
18895    '\u0162': 'T',  '\u0164': 'T', '\u0166': 'T',
18896    '\u0163': 't',  '\u0165': 't', '\u0167': 't',
18897    '\u0168': 'U',  '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
18898    '\u0169': 'u',  '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
18899    '\u0174': 'W',  '\u0175': 'w',
18900    '\u0176': 'Y',  '\u0177': 'y', '\u0178': 'Y',
18901    '\u0179': 'Z',  '\u017b': 'Z', '\u017d': 'Z',
18902    '\u017a': 'z',  '\u017c': 'z', '\u017e': 'z',
18903    '\u0132': 'IJ', '\u0133': 'ij',
18904    '\u0152': 'Oe', '\u0153': 'oe',
18905    '\u0149': "'n", '\u017f': 's'
18906  };
18907
18908  /** Used to match Latin Unicode letters (excluding mathematical operators). */
18909  var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
18910
18911  /** Used to compose unicode character classes. */
18912  var rsComboMarksRange = '\\u0300-\\u036f',
18913      reComboHalfMarksRange = '\\ufe20-\\ufe2f',
18914      rsComboSymbolsRange = '\\u20d0-\\u20ff',
18915      rsComboMarksExtendedRange = '\\u1ab0-\\u1aff',
18916      rsComboMarksSupplementRange = '\\u1dc0-\\u1dff',
18917      rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange + rsComboMarksExtendedRange + rsComboMarksSupplementRange;
18918
18919  /** Used to compose unicode capture groups. */
18920  var rsCombo = '[' + rsComboRange + ']';
18921
18922  /**
18923   * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
18924   * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
18925   */
18926  var reComboMark = RegExp(rsCombo, 'g');
18927
18928  function deburrLetter (key) {
18929    return deburredLetters[key];
18930  };
18931
18932  function normalizeToBase (string) {
18933    string = string.toString();
18934    return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
18935  }
18936
18937  // List of HTML entities for escaping.
18938  var escapeMap = {
18939    '&': '&amp;',
18940    '<': '&lt;',
18941    '>': '&gt;',
18942    '"': '&quot;',
18943    "'": '&#x27;',
18944    '`': '&#x60;'
18945  };
18946
18947  var unescapeMap = {
18948    '&amp;': '&',
18949    '&lt;': '<',
18950    '&gt;': '>',
18951    '&quot;': '"',
18952    '&#x27;': "'",
18953    '&#x60;': '`'
18954  };
18955
18956  // Functions for escaping and unescaping strings to/from HTML interpolation.
18957  var createEscaper = function (map) {
18958    var escaper = function (match) {
18959      return map[match];
18960    };
18961    // Regexes for identifying a key that needs to be escaped.
18962    var source = '(?:' + Object.keys(map).join('|') + ')';
18963    var testRegexp = RegExp(source);
18964    var replaceRegexp = RegExp(source, 'g');
18965    return function (string) {
18966      string = string == null ? '' : '' + string;
18967      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
18968    };
18969  };
18970
18971  var htmlEscape = createEscaper(escapeMap);
18972  var htmlUnescape = createEscaper(unescapeMap);
18973
18974  /**
18975   * ------------------------------------------------------------------------
18976   * Constants
18977   * ------------------------------------------------------------------------
18978   */
18979
18980  var keyCodeMap = {
18981    32: ' ',
18982    48: '0',
18983    49: '1',
18984    50: '2',
18985    51: '3',
18986    52: '4',
18987    53: '5',
18988    54: '6',
18989    55: '7',
18990    56: '8',
18991    57: '9',
18992    59: ';',
18993    65: 'A',
18994    66: 'B',
18995    67: 'C',
18996    68: 'D',
18997    69: 'E',
18998    70: 'F',
18999    71: 'G',
19000    72: 'H',
19001    73: 'I',
19002    74: 'J',
19003    75: 'K',
19004    76: 'L',
19005    77: 'M',
19006    78: 'N',
19007    79: 'O',
19008    80: 'P',
19009    81: 'Q',
19010    82: 'R',
19011    83: 'S',
19012    84: 'T',
19013    85: 'U',
19014    86: 'V',
19015    87: 'W',
19016    88: 'X',
19017    89: 'Y',
19018    90: 'Z',
19019    96: '0',
19020    97: '1',
19021    98: '2',
19022    99: '3',
19023    100: '4',
19024    101: '5',
19025    102: '6',
19026    103: '7',
19027    104: '8',
19028    105: '9'
19029  };
19030
19031  var keyCodes = {
19032    ESCAPE: 27, // KeyboardEvent.which value for Escape (Esc) key
19033    ENTER: 13, // KeyboardEvent.which value for Enter key
19034    SPACE: 32, // KeyboardEvent.which value for space key
19035    TAB: 9, // KeyboardEvent.which value for tab key
19036    ARROW_UP: 38, // KeyboardEvent.which value for up arrow key
19037    ARROW_DOWN: 40 // KeyboardEvent.which value for down arrow key
19038  }
19039
19040  var version = {
19041    success: false,
19042    major: '3'
19043  };
19044
19045  try {
19046    version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
19047    version.major = version.full[0];
19048    version.success = true;
19049  } catch (err) {
19050    console.warn(
19051      'There was an issue retrieving Bootstrap\'s version. ' +
19052      'Ensure Bootstrap is being loaded before bootstrap-select and there is no namespace collision. ' +
19053      'If loading Bootstrap asynchronously, the version may need to be manually specified via $.fn.selectpicker.Constructor.BootstrapVersion.',
19054      err
19055    );
19056  }
19057
19058  var selectId = 0;
19059
19060  var EVENT_KEY = '.bs.select';
19061
19062  var classNames = {
19063    DISABLED: 'disabled',
19064    DIVIDER: 'divider',
19065    SHOW: 'open',
19066    DROPUP: 'dropup',
19067    MENU: 'dropdown-menu',
19068    MENURIGHT: 'dropdown-menu-right',
19069    MENULEFT: 'dropdown-menu-left',
19070    // to-do: replace with more advanced template/customization options
19071    BUTTONCLASS: 'btn-default',
19072    POPOVERHEADER: 'popover-title'
19073  }
19074
19075  var Selector = {
19076    MENU: '.' + classNames.MENU
19077  }
19078
19079  if (version.major === '4') {
19080    classNames.DIVIDER = 'dropdown-divider';
19081    classNames.SHOW = 'show';
19082    classNames.BUTTONCLASS = 'btn-light';
19083    classNames.POPOVERHEADER = 'popover-header';
19084  }
19085
19086  var REGEXP_ARROW = new RegExp(keyCodes.ARROW_UP + '|' + keyCodes.ARROW_DOWN);
19087  var REGEXP_TAB_OR_ESCAPE = new RegExp('^' + keyCodes.TAB + '$|' + keyCodes.ESCAPE);
19088
19089  var Selectpicker = function (element, options) {
19090    var that = this;
19091
19092    // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
19093    if (!valHooks.useDefault) {
19094      $.valHooks.select.set = valHooks._set;
19095      valHooks.useDefault = true;
19096    }
19097
19098    this.$element = $(element);
19099    this.$newElement = null;
19100    this.$button = null;
19101    this.$menu = null;
19102    this.options = options;
19103    this.selectpicker = {
19104      main: {
19105        // store originalIndex (key) and newIndex (value) in this.selectpicker.main.map.newIndex for fast accessibility
19106        // allows us to do this.main.elements[this.selectpicker.main.map.newIndex[index]] to select an element based on the originalIndex
19107        map: {
19108          newIndex: {},
19109          originalIndex: {}
19110        }
19111      },
19112      current: {
19113        map: {}
19114      }, // current changes if a search is in progress
19115      search: {
19116        map: {}
19117      },
19118      view: {},
19119      keydown: {
19120        keyHistory: '',
19121        resetKeyHistory: {
19122          start: function () {
19123            return setTimeout(function () {
19124              that.selectpicker.keydown.keyHistory = '';
19125            }, 800);
19126          }
19127        }
19128      }
19129    };
19130    // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
19131    // data-attribute)
19132    if (this.options.title === null) {
19133      this.options.title = this.$element.attr('title');
19134    }
19135
19136    // Format window padding
19137    var winPad = this.options.windowPadding;
19138    if (typeof winPad === 'number') {
19139      this.options.windowPadding = [winPad, winPad, winPad, winPad];
19140    }
19141
19142    // Expose public methods
19143    this.val = Selectpicker.prototype.val;
19144    this.render = Selectpicker.prototype.render;
19145    this.refresh = Selectpicker.prototype.refresh;
19146    this.setStyle = Selectpicker.prototype.setStyle;
19147    this.selectAll = Selectpicker.prototype.selectAll;
19148    this.deselectAll = Selectpicker.prototype.deselectAll;
19149    this.destroy = Selectpicker.prototype.destroy;
19150    this.remove = Selectpicker.prototype.remove;
19151    this.show = Selectpicker.prototype.show;
19152    this.hide = Selectpicker.prototype.hide;
19153
19154    this.init();
19155  };
19156
19157  Selectpicker.VERSION = '1.13.5';
19158
19159  Selectpicker.BootstrapVersion = version.major;
19160
19161  // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
19162  Selectpicker.DEFAULTS = {
19163    noneSelectedText: 'Nothing selected',
19164    noneResultsText: 'No results matched {0}',
19165    countSelectedText: function (numSelected, numTotal) {
19166      return (numSelected == 1) ? '{0} item selected' : '{0} items selected';
19167    },
19168    maxOptionsText: function (numAll, numGroup) {
19169      return [
19170        (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
19171        (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
19172      ];
19173    },
19174    selectAllText: 'Select All',
19175    deselectAllText: 'Deselect All',
vendor: 8,238 bytes, lines 19176-19418
19176    doneButton: false,
19177    doneButtonText: 'Close',
19178    multipleSeparator: ', ',
19179    styleBase: 'btn',
19180    style: classNames.BUTTONCLASS,
19181    size: 'auto',
19182    title: null,
19183    selectedTextFormat: 'values',
19184    width: false,
19185    container: false,
19186    hideDisabled: false,
19187    showSubtext: false,
19188    showIcon: true,
19189    showContent: true,
19190    dropupAuto: true,
19191    header: false,
19192    liveSearch: false,
19193    liveSearchPlaceholder: null,
19194    liveSearchNormalize: false,
19195    liveSearchStyle: 'contains',
19196    actionsBox: false,
19197    iconBase: 'glyphicon',
19198    tickIcon: 'glyphicon-ok',
19199    showTick: false,
19200    template: {
19201      caret: '<span class="caret"></span>'
19202    },
19203    maxOptions: false,
19204    mobile: false,
19205    selectOnTab: false,
19206    dropdownAlignRight: false,
19207    windowPadding: 0,
19208    virtualScroll: 600,
19209    display: false
19210  };
19211
19212  if (version.major === '4') {
19213    Selectpicker.DEFAULTS.style = 'btn-light';
19214    Selectpicker.DEFAULTS.iconBase = '';
19215    Selectpicker.DEFAULTS.tickIcon = 'bs-ok-default';
19216  }
19217
19218  Selectpicker.prototype = {
19219
19220    constructor: Selectpicker,
19221
19222    init: function () {
19223      var that = this,
19224          id = this.$element.attr('id');
19225
19226      this.selectId = selectId++;
19227
19228      this.$element.addClass('bs-select-hidden');
19229
19230      this.multiple = this.$element.prop('multiple');
19231      this.autofocus = this.$element.prop('autofocus');
19232      this.$newElement = this.createDropdown();
19233      this.createLi();
19234      this.$element
19235        .after(this.$newElement)
19236        .prependTo(this.$newElement);
19237      this.$button = this.$newElement.children('button');
19238      this.$menu = this.$newElement.children(Selector.MENU);
19239      this.$menuInner = this.$menu.children('.inner');
19240      this.$searchbox = this.$menu.find('input');
19241
19242      this.$element.removeClass('bs-select-hidden');
19243
19244      if (this.options.dropdownAlignRight === true) this.$menu.addClass(classNames.MENURIGHT);
19245
19246      if (typeof id !== 'undefined') {
19247        this.$button.attr('data-id', id);
19248      }
19249
19250      this.checkDisabled();
19251      this.clickListener();
19252      if (this.options.liveSearch) this.liveSearchListener();
19253      this.render();
19254      this.setStyle();
19255      this.setWidth();
19256      if (this.options.container) {
19257        this.selectPosition();
19258      } else {
19259        this.$element.on('hide' + EVENT_KEY, function () {
19260          if (that.isVirtual()) {
19261            // empty menu on close
19262            var menuInner = that.$menuInner[0],
19263                emptyMenu = menuInner.firstChild.cloneNode(false);
19264
19265            // replace the existing UL with an empty one - this is faster than $.empty() or innerHTML = ''
19266            menuInner.replaceChild(emptyMenu, menuInner.firstChild);
19267            menuInner.scrollTop = 0;
19268          }
19269        });
19270      }
19271      this.$menu.data('this', this);
19272      this.$newElement.data('this', this);
19273      if (this.options.mobile) this.mobile();
19274
19275      this.$newElement.on({
19276        'hide.bs.dropdown': function (e) {
19277          that.$menuInner.attr('aria-expanded', false);
19278          that.$element.trigger('hide' + EVENT_KEY, e);
19279        },
19280        'hidden.bs.dropdown': function (e) {
19281          that.$element.trigger('hidden' + EVENT_KEY, e);
19282        },
19283        'show.bs.dropdown': function (e) {
19284          that.$menuInner.attr('aria-expanded', true);
19285          that.$element.trigger('show' + EVENT_KEY, e);
19286        },
19287        'shown.bs.dropdown': function (e) {
19288          that.$element.trigger('shown' + EVENT_KEY, e);
19289        }
19290      });
19291
19292      if (that.$element[0].hasAttribute('required')) {
19293        this.$element.on('invalid', function () {
19294          that.$button.addClass('bs-invalid');
19295
19296          that.$element
19297            .on('shown' + EVENT_KEY + '.invalid', function () {
19298              that.$element
19299                .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
19300                .off('shown' + EVENT_KEY + '.invalid');
19301            })
19302            .on('rendered' + EVENT_KEY, function () {
19303              // if select is no longer invalid, remove the bs-invalid class
19304              if (this.validity.valid) that.$button.removeClass('bs-invalid');
19305              that.$element.off('rendered' + EVENT_KEY);
19306            });
19307
19308          that.$button.on('blur' + EVENT_KEY, function () {
19309            that.$element.focus().blur();
19310            that.$button.off('blur' + EVENT_KEY);
19311          });
19312        });
19313      }
19314
19315      setTimeout(function () {
19316        that.$element.trigger('loaded' + EVENT_KEY);
19317      });
19318    },
19319
19320    createDropdown: function () {
19321      // Options
19322      // If we are multiple or showTick option is set, then add the show-tick class
19323      var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
19324          autofocus = this.autofocus ? ' autofocus' : '';
19325
19326      // Elements
19327      var drop,
19328          header = '',
19329          searchbox = '',
19330          actionsbox = '',
19331          donebutton = '';
19332
19333      if (this.options.header) {
19334        header =
19335          '<div class="' + classNames.POPOVERHEADER + '">' +
19336            '<button type="button" class="close" aria-hidden="true">&times;</button>' +
19337              this.options.header +
19338          '</div>';
19339      }
19340
19341      if (this.options.liveSearch) {
19342        searchbox =
19343          '<div class="bs-searchbox">' +
19344            '<input type="text" class="form-control" autocomplete="off"' +
19345              (
19346                this.options.liveSearchPlaceholder === null ? ''
19347                :
19348                ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"'
19349              ) +
19350              ' role="textbox" aria-label="Search">' +
19351          '</div>';
19352      }
19353
19354      if (this.multiple && this.options.actionsBox) {
19355        actionsbox =
19356          '<div class="bs-actionsbox">' +
19357            '<div class="btn-group btn-group-sm btn-block">' +
19358              '<button type="button" class="actions-btn bs-select-all btn ' + classNames.BUTTONCLASS + '">' +
19359                this.options.selectAllText +
19360              '</button>' +
19361              '<button type="button" class="actions-btn bs-deselect-all btn ' + classNames.BUTTONCLASS + '">' +
19362                this.options.deselectAllText +
19363              '</button>' +
19364            '</div>' +
19365          '</div>';
19366      }
19367
19368      if (this.multiple && this.options.doneButton) {
19369        donebutton =
19370          '<div class="bs-donebutton">' +
19371            '<div class="btn-group btn-block">' +
19372              '<button type="button" class="btn btn-sm ' + classNames.BUTTONCLASS + '">' +
19373                this.options.doneButtonText +
19374              '</button>' +
19375            '</div>' +
19376          '</div>';
19377      }
19378
19379      drop =
19380        '<div class="dropdown bootstrap-select' + showTick + '">' +
19381          '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" ' + (this.options.display === 'static' ? 'data-display="static"' : '') + 'data-toggle="dropdown"' + autofocus + ' role="button">' +
19382            '<div class="filter-option">' +
19383              '<div class="filter-option-inner">' +
19384                '<div class="filter-option-inner-inner"></div>' +
19385              '</div> ' +
19386            '</div>' +
19387            (
19388              version.major === '4' ? ''
19389              :
19390              '<span class="bs-caret">' +
19391                this.options.template.caret +
19392              '</span>'
19393            ) +
19394          '</button>' +
19395          '<div class="' + classNames.MENU + ' ' + (version.major === '4' ? '' : classNames.SHOW) + '" role="combobox">' +
19396            header +
19397            searchbox +
19398            actionsbox +
19399            '<div class="inner ' + classNames.SHOW + '" role="listbox" aria-expanded="false" tabindex="-1">' +
19400                '<ul class="' + classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '') + '">' +
19401                '</ul>' +
19402            '</div>' +
19403            donebutton +
19404          '</div>' +
19405        '</div>';
19406
19407      return $(drop);
19408    },
19409
19410    setPositionData: function () {
19411      this.selectpicker.view.canHighlight = [];
19412
19413      for (var i = 0; i < this.selectpicker.current.data.length; i++) {
19414        var li = this.selectpicker.current.data[i],
19415            canHighlight = true;
19416
19417        if (li.type === 'divider') {
19418          canHighlight = false;
19419          li.height = this.sizeInfo.dividerHeight;
19420        } else if (li.type === 'optgroup-label') {
19421          canHighlight = false;
19422          li.height = this.sizeInfo.dropdownHeaderHeight;
19423        } else {
19424          li.height = this.sizeInfo.liHeight;
19425        }
19426
19427        if (li.disabled) canHighlight = false;
19428
19429        this.selectpicker.view.canHighlight.push(canHighlight);
19430
19431        li.position = (i === 0 ? 0 : this.selectpicker.current.data[i - 1].position) + li.height;
19432      }
19433    },
19434
19435    isVirtual: function () {
19436      return (this.options.virtualScroll !== false) && (this.selectpicker.main.elements.length >= this.options.virtualScroll) || this.options.virtualScroll === true;
19437    },
19438
19439    createView: function (isSearching, scrollTop) {
19440      scrollTop = scrollTop || 0;
19441
19442      var that = this;
19443
19444      this.selectpicker.current = isSearching ? this.selectpicker.search : this.selectpicker.main;
19445
19446      var active = [];
19447      var selected;
19448      var prevActive;
19449
19450      this.setPositionData();
19451
19452      scroll(scrollTop, true);
19453
19454      this.$menuInner.off('scroll.createView').on('scroll.createView', function (e, updateValue) {
19455        if (!that.noScroll) scroll(this.scrollTop, updateValue);
19456        that.noScroll = false;
19457      });
19458
19459      function scroll (scrollTop, init) {
19460        var size = that.selectpicker.current.elements.length,
19461            chunks = [],
19462            chunkSize,
19463            chunkCount,
19464            firstChunk,
19465            lastChunk,
19466            currentChunk,
19467            prevPositions,
19468            positionIsDifferent,
19469            previousElements,
19470            menuIsDifferent = true,
19471            isVirtual = that.isVirtual();
19472
19473        that.selectpicker.view.scrollTop = scrollTop;
19474
19475        if (isVirtual === true) {
19476          // if an option that is encountered that is wider than the current menu width, update the menu width accordingly
19477          if (that.sizeInfo.hasScrollBar && that.$menu[0].offsetWidth > that.sizeInfo.totalMenuWidth) {
19478            that.sizeInfo.menuWidth = that.$menu[0].offsetWidth;
19479            that.sizeInfo.totalMenuWidth = that.sizeInfo.menuWidth + that.sizeInfo.scrollBarWidth;
19480            that.$menu.css('min-width', that.sizeInfo.menuWidth);
19481          }
19482        }
19483
19484        chunkSize = Math.ceil(that.sizeInfo.menuInnerHeight / that.sizeInfo.liHeight * 1.5); // number of options in a chunk
19485        chunkCount = Math.round(size / chunkSize) || 1; // number of chunks
19486
19487        for (var i = 0; i < chunkCount; i++) {
19488          var endOfChunk = (i + 1) * chunkSize;
19489
19490          if (i === chunkCount - 1) {
19491            endOfChunk = size;
19492          }
19493
19494          chunks[i] = [
19495            (i) * chunkSize + (!i ? 0 : 1),
19496            endOfChunk
19497          ];
19498
19499          if (!size) break;
19500
19501          if (currentChunk === undefined && scrollTop <= that.selectpicker.current.data[endOfChunk - 1].position - that.sizeInfo.menuInnerHeight) {
19502            currentChunk = i;
19503          }
19504        }
19505
19506        if (currentChunk === undefined) currentChunk = 0;
19507
19508        prevPositions = [that.selectpicker.view.position0, that.selectpicker.view.position1];
19509
19510        // always display previous, current, and next chunks
19511        firstChunk = Math.max(0, currentChunk - 1);
19512        lastChunk = Math.min(chunkCount - 1, currentChunk + 1);
19513
19514        that.selectpicker.view.position0 = Math.max(0, chunks[firstChunk][0]) || 0;
19515        that.selectpicker.view.position1 = Math.min(size, chunks[lastChunk][1]) || 0;
19516
19517        positionIsDifferent = prevPositions[0] !== that.selectpicker.view.position0 || prevPositions[1] !== that.selectpicker.view.position1;
19518
19519        if (that.activeIndex !== undefined) {
19520          prevActive = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.prevActiveIndex]];
19521          active = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.activeIndex]];
19522          selected = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.selectedIndex]];
19523
19524          if (init) {
19525            if (that.activeIndex !== that.selectedIndex) {
19526              active.classList.remove('active');
19527              if (active.firstChild) active.firstChild.classList.remove('active');
19528            }
19529            that.activeIndex = undefined;
19530          }
19531
19532          if (that.activeIndex && that.activeIndex !== that.selectedIndex && selected && selected.length) {
19533            selected.classList.remove('active');
19534            if (selected.firstChild) selected.firstChild.classList.remove('active');
19535          }
19536        }
19537
19538        if (that.prevActiveIndex !== undefined && that.prevActiveIndex !== that.activeIndex && that.prevActiveIndex !== that.selectedIndex && prevActive && prevActive.length) {
19539          prevActive.classList.remove('active');
19540          if (prevActive.firstChild) prevActive.firstChild.classList.remove('active');
19541        }
19542
19543        if (init || positionIsDifferent) {
19544          previousElements = that.selectpicker.view.visibleElements ? that.selectpicker.view.visibleElements.slice() : [];
19545
19546          that.selectpicker.view.visibleElements = that.selectpicker.current.elements.slice(that.selectpicker.view.position0, that.selectpicker.view.position1);
19547
19548          that.setOptionStatus();
19549
19550          // if searching, check to make sure the list has actually been updated before updating DOM
19551          // this prevents unnecessary repaints
19552          if (isSearching || (isVirtual === false && init)) menuIsDifferent = !isEqual(previousElements, that.selectpicker.view.visibleElements);
19553
19554          // if virtual scroll is disabled and not searching,
19555          // menu should never need to be updated more than once
19556          if ((init || isVirtual === true) && menuIsDifferent) {
19557            var menuInner = that.$menuInner[0],
19558                menuFragment = document.createDocumentFragment(),
19559                emptyMenu = menuInner.firstChild.cloneNode(false),
19560                marginTop,
19561                marginBottom,
19562                elements = isVirtual === true ? that.selectpicker.view.visibleElements : that.selectpicker.current.elements;
19563
19564            // replace the existing UL with an empty one - this is faster than $.empty()
19565            menuInner.replaceChild(emptyMenu, menuInner.firstChild);
19566
19567            for (var i = 0, visibleElementsLen = elements.length; i < visibleElementsLen; i++) {
19568              menuFragment.appendChild(elements[i]);
19569            }
19570
19571            if (isVirtual === true) {
19572              marginTop = (that.selectpicker.view.position0 === 0 ? 0 : that.selectpicker.current.data[that.selectpicker.view.position0 - 1].position);
19573              marginBottom = (that.selectpicker.view.position1 > size - 1 ? 0 : that.selectpicker.current.data[size - 1].position - that.selectpicker.current.data[that.selectpicker.view.position1 - 1].position);
19574
19575              menuInner.firstChild.style.marginTop = marginTop + 'px';
19576              menuInner.firstChild.style.marginBottom = marginBottom + 'px';
19577            }
19578
19579            menuInner.firstChild.appendChild(menuFragment);
19580          }
19581        }
19582
19583        that.prevActiveIndex = that.activeIndex;
19584
19585        if (!that.options.liveSearch) {
19586          that.$menuInner.focus();
19587        } else if (isSearching && init) {
19588          var index = 0,
19589              newActive;
19590
19591          if (!that.selectpicker.view.canHighlight[index]) {
19592            index = 1 + that.selectpicker.view.canHighlight.slice(1).indexOf(true);
19593          }
19594
19595          newActive = that.selectpicker.view.visibleElements[index];
19596
19597          if (that.selectpicker.view.currentActive) {
19598            that.selectpicker.view.currentActive.classList.remove('active');
19599            if (that.selectpicker.view.currentActive.firstChild) that.selectpicker.view.currentActive.firstChild.classList.remove('active');
19600          }
19601
19602          if (newActive) {
19603            newActive.classList.add('active');
19604            if (newActive.firstChild) newActive.firstChild.classList.add('active');
19605          }
19606
19607          that.activeIndex = that.selectpicker.current.map.originalIndex[index];
19608        }
19609      }
19610
19611      $(window)
19612        .off('resize' + EVENT_KEY + '.' + this.selectId + '.createView')
19613        .on('resize' + EVENT_KEY + '.' + this.selectId + '.createView', function () {
19614          var isActive = that.$newElement.hasClass(classNames.SHOW);
19615
19616          if (isActive) scroll(that.$menuInner[0].scrollTop);
19617        });
19618    },
19619
19620    createLi: function () {
19621      var that = this,
19622          mainElements = [],
19623          hiddenOptions = {},
19624          widestOption,
19625          availableOptionsCount = 0,
19626          widestOptionLength = 0,
19627          mainData = [],
19628          optID = 0,
19629          headerIndex = 0,
19630          liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure newIndex is correct
19631
19632      if (!this.selectpicker.view.titleOption) this.selectpicker.view.titleOption = document.createElement('option');
19633
19634      var elementTemplates = {
19635            span: document.createElement('span'),
19636            subtext: document.createElement('small'),
19637            a: document.createElement('a'),
19638            li: document.createElement('li'),
19639            whitespace: document.createTextNode('\u00A0')
19640          },
19641          checkMark,
19642          fragment = document.createDocumentFragment();
19643
19644      if (that.options.showTick || that.multiple) {
19645        checkMark = elementTemplates.span.cloneNode(false);
19646        checkMark.className = that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark';
19647        elementTemplates.a.appendChild(checkMark);
19648      }
19649
19650      elementTemplates.a.setAttribute('role', 'option');
19651
19652      elementTemplates.subtext.className = 'text-muted';
19653
19654      elementTemplates.text = elementTemplates.span.cloneNode(false);
19655      elementTemplates.text.className = 'text';
19656
19657      // Helper functions
19658      /**
19659       * @param content
19660       * @param [classes]
19661       * @param [optgroup]
19662       * @returns {HTMLElement}
19663       */
19664      var generateLI = function (content, classes, optgroup) {
19665        var li = elementTemplates.li.cloneNode(false);
19666
19667        if (content) {
19668          if (content.nodeType === 1 || content.nodeType === 11) {
19669            li.appendChild(content);
19670          } else {
19671            li.innerHTML = content;
19672          }
19673        }
19674
19675        if (typeof classes !== 'undefined' && classes !== '') li.className = classes;
19676        if (typeof optgroup !== 'undefined' && optgroup !== null) li.classList.add('optgroup-' + optgroup);
19677
19678        return li;
19679      };
19680
19681      /**
19682       * @param text
19683       * @param [classes]
19684       * @param [inline]
19685       * @returns {string}
19686       */
19687      var generateA = function (text, classes, inline) {
19688        var a = elementTemplates.a.cloneNode(true);
19689
19690        if (text) {
19691          if (text.nodeType === 11) {
19692            a.appendChild(text);
19693          } else {
19694            a.insertAdjacentHTML('beforeend', text);
19695          }
19696        }
19697
19698        if (typeof classes !== 'undefined' && classes !== '') a.className = classes;
19699        if (version.major === '4') a.classList.add('dropdown-item');
19700        if (inline) a.setAttribute('style', inline);
19701
19702        return a;
19703      };
19704
19705      var generateText = function (options) {
19706        var textElement = elementTemplates.text.cloneNode(false),
19707            optionSubtextElement,
19708            optionIconElement;
19709
19710        if (options.optionContent) {
19711          textElement.innerHTML = options.optionContent;
19712        } else {
19713          textElement.textContent = options.text;
19714
19715          if (options.optionIcon) {
19716            var whitespace = elementTemplates.whitespace.cloneNode(false);
19717
19718            optionIconElement = elementTemplates.span.cloneNode(false);
19719            optionIconElement.className = that.options.iconBase + ' ' + options.optionIcon;
19720
19721            fragment.appendChild(optionIconElement);
19722            fragment.appendChild(whitespace);
19723          }
19724
19725          if (options.optionSubtext) {
19726            optionSubtextElement = elementTemplates.subtext.cloneNode(false);
19727            optionSubtextElement.innerHTML = options.optionSubtext;
19728            textElement.appendChild(optionSubtextElement);
19729          }
19730        }
19731
19732        fragment.appendChild(textElement);
19733
19734        return fragment;
19735      };
19736
19737      var generateLabel = function (options) {
19738        var labelTextElement = elementTemplates.text.cloneNode(false),
19739            labelSubtextElement,
19740            labelIconElement;
19741
19742        labelTextElement.innerHTML = options.labelEscaped;
19743
19744        if (options.labelIcon) {
19745          var whitespace = elementTemplates.whitespace.cloneNode(false);
19746
19747          labelIconElement = elementTemplates.span.cloneNode(false);
19748          labelIconElement.className = that.options.iconBase + ' ' + options.labelIcon;
19749
19750          fragment.appendChild(labelIconElement);
19751          fragment.appendChild(whitespace);
19752        }
19753
19754        if (options.labelSubtext) {
19755          labelSubtextElement = elementTemplates.subtext.cloneNode(false);
19756          labelSubtextElement.textContent = options.labelSubtext;
19757          labelTextElement.appendChild(labelSubtextElement);
19758        }
19759
19760        fragment.appendChild(labelTextElement);
19761
19762        return fragment;
19763      }
19764
19765      if (this.options.title && !this.multiple) {
19766        // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
19767        // since newIndex is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
19768        liIndex--;
19769
19770        var element = this.$element[0],
19771            isSelected = false,
19772            titleNotAppended = !this.selectpicker.view.titleOption.parentNode;
19773
19774        if (titleNotAppended) {
19775          // Use native JS to prepend option (faster)
19776          this.selectpicker.view.titleOption.className = 'bs-title-option';
19777          this.selectpicker.view.titleOption.value = '';
19778
19779          // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
19780          // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
19781          // if so, the select will have the data-selected attribute
19782          var $opt = $(element.options[element.selectedIndex]);
19783          isSelected = $opt.attr('selected') === undefined && this.$element.data('selected') === undefined;
19784        }
19785
19786        if (titleNotAppended || this.selectpicker.view.titleOption.index !== 0) {
19787          element.insertBefore(this.selectpicker.view.titleOption, element.firstChild);
19788        }
19789
19790        // Set selected *after* appending to select,
19791        // otherwise the option doesn't get selected in IE
19792        // set using selectedIndex, as setting the selected attr to true here doesn't work in IE11
19793        if (isSelected) element.selectedIndex = 0;
19794      }
19795
19796      var $selectOptions = this.$element.find('option');
19797
19798      $selectOptions.each(function (index) {
19799        var $this = $(this);
19800
19801        liIndex++;
19802
19803        if ($this.hasClass('bs-title-option')) return;
19804
19805        var thisData = $this.data();
19806
19807        // Get the class and text for the option
19808        var optionClass = this.className || '',
19809            inline = htmlEscape(this.style.cssText),
19810            optionContent = thisData.content,
19811            text = this.textContent,
19812            tokens = thisData.tokens,
19813            subtext = thisData.subtext,
19814            icon = thisData.icon,
19815            $parent = $this.parent(),
19816            parent = $parent[0],
19817            isOptgroup = parent.tagName === 'OPTGROUP',
19818            isOptgroupDisabled = isOptgroup && parent.disabled,
19819            isDisabled = this.disabled || isOptgroupDisabled,
19820            prevHiddenIndex,
19821            showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP',
19822            textElement,
19823            labelElement,
19824            prevHidden;
19825
19826        var parentData = $parent.data();
19827
19828        if ((thisData.hidden === true || this.hidden) || (that.options.hideDisabled && (isDisabled || isOptgroupDisabled))) {
19829          // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
19830          // used to determine whether or not a divider should be placed after an optgroup if there are
19831          // hidden options between the optgroup and the first visible option
19832          prevHiddenIndex = thisData.prevHiddenIndex;
19833          $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
19834
19835          liIndex--;
19836
19837          hiddenOptions[index] = {
19838            type: 'hidden',
19839            data: thisData
19840          }
19841
19842          // if previous element is not an optgroup
19843          if (!showDivider) {
19844            if (prevHiddenIndex !== undefined) {
19845              // select the element **before** the first hidden element in the group
19846              prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling;
19847
19848              if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
19849                showDivider = true;
19850              }
19851            }
19852          }
19853
19854          if (showDivider && mainData[mainData.length - 1].type !== 'divider') {
19855            liIndex++;
19856            mainElements.push(
19857              generateLI(
19858                false,
19859                classNames.DIVIDER,
19860                optID + 'div'
19861              )
19862            );
19863            mainData.push({
19864              type: 'divider',
19865              optID: optID
19866            });
19867          }
19868
19869          return;
19870        }
19871
19872        if (isOptgroup && thisData.divider !== true) {
19873          if (that.options.hideDisabled && isDisabled) {
19874            if (parentData.allOptionsDisabled === undefined) {
19875              var $options = $parent.children();
19876              $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
19877            }
19878
19879            if ($parent.data('allOptionsDisabled')) {
19880              liIndex--;
19881              return;
19882            }
19883          }
19884
19885          var optGroupClass = ' ' + parent.className || '',
19886              previousOption = this.previousElementSibling;
19887
19888          prevHiddenIndex = thisData.prevHiddenIndex;
19889
19890          if (prevHiddenIndex !== undefined) {
19891            previousOption = $selectOptions[prevHiddenIndex].previousElementSibling;
19892          }
19893
19894          if (!previousOption) { // Is it the first option of the optgroup?
19895            optID += 1;
19896
19897            // Get the opt group label
19898            var label = parent.label,
19899                labelEscaped = htmlEscape(label),
19900                labelSubtext = parentData.subtext,
19901                labelIcon = parentData.icon;
19902
19903            if (index !== 0 && mainElements.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
19904              liIndex++;
19905              mainElements.push(
19906                generateLI(
19907                  false,
19908                  classNames.DIVIDER,
19909                  optID + 'div'
19910                )
19911              );
19912              mainData.push({
19913                type: 'divider',
19914                optID: optID
19915              });
19916            }
19917            liIndex++;
19918
19919            labelElement = generateLabel({
19920              labelEscaped: labelEscaped,
19921              labelSubtext: labelSubtext,
19922              labelIcon: labelIcon
19923            });
19924
19925            mainElements.push(generateLI(labelElement, 'dropdown-header' + optGroupClass, optID));
19926            mainData.push({
19927              content: labelEscaped,
19928              subtext: labelSubtext,
19929              type: 'optgroup-label',
19930              optID: optID
19931            });
19932
19933            headerIndex = liIndex - 1;
19934          }
19935
19936          textElement = generateText({
19937            text: text,
19938            optionContent: optionContent,
19939            optionSubtext: subtext,
19940            optionIcon: icon
19941          });
19942
19943          mainElements.push(generateLI(generateA(textElement, 'opt ' + optionClass + optGroupClass, inline), '', optID));
19944          mainData.push({
19945            content: optionContent || text,
19946            subtext: subtext,
19947            tokens: tokens,
19948            type: 'option',
19949            optID: optID,
19950            headerIndex: headerIndex,
19951            lastIndex: headerIndex + parent.childElementCount,
19952            originalIndex: index,
19953            data: thisData
19954          });
19955
19956          availableOptionsCount++;
19957        } else if (thisData.divider === true) {
19958          mainElements.push(generateLI(false, classNames.DIVIDER));
19959          mainData.push({
19960            type: 'divider',
19961            originalIndex: index,
19962            data: thisData
19963          });
19964        } else {
19965          // if previous element is not an optgroup and hideDisabled is true
19966          if (!showDivider && that.options.hideDisabled) {
19967            prevHiddenIndex = thisData.prevHiddenIndex;
19968
19969            if (prevHiddenIndex !== undefined) {
19970              // select the element **before** the first hidden element in the group
19971              prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling;
19972
19973              if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
19974                showDivider = true;
19975              }
19976            }
19977          }
19978
19979          if (showDivider && mainData[mainData.length - 1].type !== 'divider') {
19980            liIndex++;
19981            mainElements.push(
19982              generateLI(
19983                false,
19984                classNames.DIVIDER,
19985                optID + 'div'
19986              )
19987            );
19988            mainData.push({
19989              type: 'divider',
19990              optID: optID
19991            });
19992          }
19993
19994          textElement = generateText({
19995            text: text,
19996            optionContent: optionContent,
19997            optionSubtext: subtext,
19998            optionIcon: icon
19999          });
20000
20001          mainElements.push(generateLI(generateA(textElement, optionClass, inline)));
20002          mainData.push({
20003            content: optionContent || text,
20004            subtext: subtext,
20005            tokens: tokens,
20006            type: 'option',
20007            originalIndex: index,
20008            data: thisData
20009          });
20010
20011          availableOptionsCount++;
20012        }
20013
20014        that.selectpicker.main.map.newIndex[index] = liIndex;
20015        that.selectpicker.main.map.originalIndex[liIndex] = index;
20016
20017        // get the most recent option info added to mainData
20018        var _mainDataLast = mainData[mainData.length - 1];
20019
20020        _mainDataLast.disabled = isDisabled;
20021
20022        var combinedLength = 0;
20023
20024        // count the number of characters in the option - not perfect, but should work in most cases
20025        if (_mainDataLast.content) combinedLength += _mainDataLast.content.length;
20026        if (_mainDataLast.subtext) combinedLength += _mainDataLast.subtext.length;
20027        // if there is an icon, ensure this option's width is checked
20028        if (icon) combinedLength += 1;
20029
20030        if (combinedLength > widestOptionLength) {
20031          widestOptionLength = combinedLength;
20032
20033          // guess which option is the widest
20034          // use this when calculating menu width
20035          // not perfect, but it's fast, and the width will be updating accordingly when scrolling
20036          widestOption = mainElements[mainElements.length - 1];
20037        }
20038      });
20039
20040      this.selectpicker.main.elements = mainElements;
20041      this.selectpicker.main.data = mainData;
20042      this.selectpicker.main.hidden = hiddenOptions;
20043
20044      this.selectpicker.current = this.selectpicker.main;
20045
20046      this.selectpicker.view.widestOption = widestOption;
20047      this.selectpicker.view.availableOptionsCount = availableOptionsCount; // faster way to get # of available options without filter
20048    },
20049
20050    findLis: function () {
20051      return this.$menuInner.find('.inner > li');
20052    },
20053
20054    render: function () {
20055      var that = this,
20056          $selectOptions = this.$element.find('option'),
20057          selectedItems = [],
20058          selectedItemsInTitle = [];
20059
20060      this.togglePlaceholder();
20061
20062      this.tabIndex();
20063
20064      for (var index = 0, len = $selectOptions.length; index < len; index++) {
20065        var i = that.selectpicker.main.map.newIndex[index],
20066            option = $selectOptions[index],
20067            optionData = that.selectpicker.main.data[i] || that.selectpicker.main.hidden[index];
20068
20069        if (option && option.selected && optionData) {
20070          selectedItems.push(option);
20071
20072          if ((selectedItemsInTitle.length < 100 && that.options.selectedTextFormat !== 'count') || selectedItems.length === 1) {
20073            var thisData = optionData.data,
20074                icon = thisData.icon && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + thisData.icon + '"></i> ' : '',
20075                subtext,
20076                titleItem;
20077
20078            if (that.options.showSubtext && thisData.subtext && !that.multiple) {
20079              subtext = ' <small class="text-muted">' + thisData.subtext + '</small>';
20080            } else {
20081              subtext = '';
20082            }
20083
20084            if (option.title) {
20085              titleItem = option.title;
20086            } else if (thisData.content && that.options.showContent) {
20087              titleItem = thisData.content.toString();
20088            } else {
20089              titleItem = icon + option.innerHTML.trim() + subtext;
20090            }
20091
20092            selectedItemsInTitle.push(titleItem);
20093          }
20094        }
20095      }
20096
20097      // Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
20098      // Convert all the values into a comma delimited string
20099      var title = !this.multiple ? selectedItemsInTitle[0] : selectedItemsInTitle.join(this.options.multipleSeparator);
20100
20101      // add ellipsis
20102      if (selectedItems.length > 50) title += '...';
20103
20104      // If this is a multiselect, and selectedTextFormat is count, then show 1 of 2 selected etc..
20105      if (this.multiple && this.options.selectedTextFormat.indexOf('count') !== -1) {
20106        var max = this.options.selectedTextFormat.split('>');
20107
20108        if ((max.length > 1 && selectedItems.length > max[1]) || (max.length === 1 && selectedItems.length >= 2)) {
20109          var totalCount = this.selectpicker.view.availableOptionsCount,
20110              tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
20111
20112          title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
20113        }
20114      }
20115
20116      if (this.options.title == undefined) {
20117        // use .attr to ensure undefined is returned if title attribute is not set
20118        this.options.title = this.$element.attr('title');
20119      }
20120
20121      if (this.options.selectedTextFormat == 'static') {
20122        title = this.options.title;
20123      }
20124
20125      // If the select doesn't have a title, then use the default, or if nothing is set at all, use noneSelectedText
20126      if (!title) {
20127        title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
20128      }
20129
20130      // strip all HTML tags and trim the result, then unescape any escaped tags
20131      this.$button[0].title = htmlUnescape(title.replace(/<[^>]*>?/g, '').trim());
20132      this.$button.find('.filter-option-inner-inner')[0].innerHTML = title;
20133
20134      this.$element.trigger('rendered' + EVENT_KEY);
20135    },
20136
20137    /**
20138     * @param [style]
20139     * @param [status]
20140     */
20141    setStyle: function (style, status) {
20142      if (this.$element.attr('class')) {
20143        this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
20144      }
20145
20146      var buttonClass = style || this.options.style;
20147
20148      if (status == 'add') {
20149        this.$button.addClass(buttonClass);
20150      } else if (status == 'remove') {
20151        this.$button.removeClass(buttonClass);
20152      } else {
20153        this.$button.removeClass(this.options.style);
20154        this.$button.addClass(buttonClass);
20155      }
20156    },
20157
20158    liHeight: function (refresh) {
20159      if (!refresh && (this.options.size === false || this.sizeInfo)) return;
20160
20161      if (!this.sizeInfo) this.sizeInfo = {};
20162
20163      var newElement = document.createElement('div'),
20164          menu = document.createElement('div'),
20165          menuInner = document.createElement('div'),
20166          menuInnerInner = document.createElement('ul'),
20167          divider = document.createElement('li'),
20168          dropdownHeader = document.createElement('li'),
20169          li = document.createElement('li'),
20170          a = document.createElement('a'),
20171          text = document.createElement('span'),
20172          header = this.options.header && this.$menu.find('.' + classNames.POPOVERHEADER).length > 0 ? this.$menu.find('.' + classNames.POPOVERHEADER)[0].cloneNode(true) : null,
20173          search = this.options.liveSearch ? document.createElement('div') : null,
20174          actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
20175          doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null,
20176          firstOption = this.$element.find('option')[0];
20177
20178      this.sizeInfo.selectWidth = this.$newElement[0].offsetWidth;
20179
20180      text.className = 'text';
20181      a.className = 'dropdown-item ' + (firstOption ? firstOption.className : '');
20182      newElement.className = this.$menu[0].parentNode.className + ' ' + classNames.SHOW;
20183      newElement.style.width = this.sizeInfo.selectWidth + 'px';
20184      if (this.options.width === 'auto') menu.style.minWidth = 0;
20185      menu.className = classNames.MENU + ' ' + classNames.SHOW;
20186      menuInner.className = 'inner ' + classNames.SHOW;
20187      menuInnerInner.className = classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '');
20188      divider.className = classNames.DIVIDER;
20189      dropdownHeader.className = 'dropdown-header';
20190
20191      text.appendChild(document.createTextNode('\u200b'));
20192      a.appendChild(text);
20193      li.appendChild(a);
20194      dropdownHeader.appendChild(text.cloneNode(true));
20195
20196      if (this.selectpicker.view.widestOption) {
20197        menuInnerInner.appendChild(this.selectpicker.view.widestOption.cloneNode(true));
20198      }
20199
20200      menuInnerInner.appendChild(li);
20201      menuInnerInner.appendChild(divider);
20202      menuInnerInner.appendChild(dropdownHeader);
20203      if (header) menu.appendChild(header);
20204      if (search) {
20205        var input = document.createElement('input');
20206        search.className = 'bs-searchbox';
20207        input.className = 'form-control';
20208        search.appendChild(input);
20209        menu.appendChild(search);
20210      }
20211      if (actions) menu.appendChild(actions);
20212      menuInner.appendChild(menuInnerInner);
20213      menu.appendChild(menuInner);
20214      if (doneButton) menu.appendChild(doneButton);
20215      newElement.appendChild(menu);
20216
20217      document.body.appendChild(newElement);
20218
20219      var liHeight = a.offsetHeight,
20220          dropdownHeaderHeight = dropdownHeader ? dropdownHeader.offsetHeight : 0,
20221          headerHeight = header ? header.offsetHeight : 0,
20222          searchHeight = search ? search.offsetHeight : 0,
20223          actionsHeight = actions ? actions.offsetHeight : 0,
20224          doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
20225          dividerHeight = $(divider).outerHeight(true),
20226          // fall back to jQuery if getComputedStyle is not supported
20227          menuStyle = window.getComputedStyle ? window.getComputedStyle(menu) : false,
20228          menuWidth = menu.offsetWidth,
20229          $menu = menuStyle ? null : $(menu),
20230          menuPadding = {
20231            vert: toInteger(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
20232                  toInteger(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
20233                  toInteger(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
20234                  toInteger(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
20235            horiz: toInteger(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
20236                  toInteger(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
20237                  toInteger(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
20238                  toInteger(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
20239          },
20240          menuExtras = {
20241            vert: menuPadding.vert +
20242                  toInteger(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
20243                  toInteger(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
20244            horiz: menuPadding.horiz +
20245                  toInteger(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
20246                  toInteger(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
20247          },
20248          scrollBarWidth;
20249
20250      menuInner.style.overflowY = 'scroll';
20251
20252      scrollBarWidth = menu.offsetWidth - menuWidth;
20253
20254      document.body.removeChild(newElement);
20255
20256      this.sizeInfo.liHeight = liHeight;
20257      this.sizeInfo.dropdownHeaderHeight = dropdownHeaderHeight;
20258      this.sizeInfo.headerHeight = headerHeight;
20259      this.sizeInfo.searchHeight = searchHeight;
20260      this.sizeInfo.actionsHeight = actionsHeight;
20261      this.sizeInfo.doneButtonHeight = doneButtonHeight;
vendor: 12,975 bytes, lines 20262-20572
20262      this.sizeInfo.dividerHeight = dividerHeight;
20263      this.sizeInfo.menuPadding = menuPadding;
20264      this.sizeInfo.menuExtras = menuExtras;
20265      this.sizeInfo.menuWidth = menuWidth;
20266      this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth;
20267      this.sizeInfo.scrollBarWidth = scrollBarWidth;
20268      this.sizeInfo.selectHeight = this.$newElement[0].offsetHeight;
20269
20270      this.setPositionData();
20271    },
20272
20273    getSelectPosition: function () {
20274      var that = this,
20275          $window = $(window),
20276          pos = that.$newElement.offset(),
20277          $container = $(that.options.container),
20278          containerPos;
20279
20280      if (that.options.container && !$container.is('body')) {
20281        containerPos = $container.offset();
20282        containerPos.top += parseInt($container.css('borderTopWidth'));
20283        containerPos.left += parseInt($container.css('borderLeftWidth'));
20284      } else {
20285        containerPos = { top: 0, left: 0 };
20286      }
20287
20288      var winPad = that.options.windowPadding;
20289
20290      this.sizeInfo.selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
20291      this.sizeInfo.selectOffsetBot = $window.height() - this.sizeInfo.selectOffsetTop - this.sizeInfo.selectHeight - containerPos.top - winPad[2];
20292      this.sizeInfo.selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
20293      this.sizeInfo.selectOffsetRight = $window.width() - this.sizeInfo.selectOffsetLeft - this.sizeInfo.selectWidth - containerPos.left - winPad[1];
20294      this.sizeInfo.selectOffsetTop -= winPad[0];
20295      this.sizeInfo.selectOffsetLeft -= winPad[3];
20296    },
20297
20298    setMenuSize: function (isAuto) {
20299      this.getSelectPosition();
20300
20301      var selectWidth = this.sizeInfo.selectWidth,
20302          liHeight = this.sizeInfo.liHeight,
20303          headerHeight = this.sizeInfo.headerHeight,
20304          searchHeight = this.sizeInfo.searchHeight,
20305          actionsHeight = this.sizeInfo.actionsHeight,
20306          doneButtonHeight = this.sizeInfo.doneButtonHeight,
20307          divHeight = this.sizeInfo.dividerHeight,
20308          menuPadding = this.sizeInfo.menuPadding,
20309          menuInnerHeight,
20310          menuHeight,
20311          divLength = 0,
20312          minHeight,
20313          _minHeight,
20314          maxHeight,
20315          menuInnerMinHeight,
20316          estimate;
20317
20318      if (this.options.dropupAuto) {
20319        // Get the estimated height of the menu without scrollbars.
20320        // This is useful for smaller menus, where there might be plenty of room
20321        // below the button without setting dropup, but we can't know
20322        // the exact height of the menu until createView is called later
20323        estimate = liHeight * this.selectpicker.current.elements.length + menuPadding.vert;
20324        this.$newElement.toggleClass(classNames.DROPUP, this.sizeInfo.selectOffsetTop - this.sizeInfo.selectOffsetBot > this.sizeInfo.menuExtras.vert && estimate + this.sizeInfo.menuExtras.vert + 50 > this.sizeInfo.selectOffsetBot);
20325      }
20326
20327      if (this.options.size === 'auto') {
20328        _minHeight = this.selectpicker.current.elements.length > 3 ? this.sizeInfo.liHeight * 3 + this.sizeInfo.menuExtras.vert - 2 : 0;
20329        menuHeight = this.sizeInfo.selectOffsetBot - this.sizeInfo.menuExtras.vert;
20330        minHeight = _minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
20331        menuInnerMinHeight = Math.max(_minHeight - menuPadding.vert, 0);
20332
20333        if (this.$newElement.hasClass(classNames.DROPUP)) {
20334          menuHeight = this.sizeInfo.selectOffsetTop - this.sizeInfo.menuExtras.vert;
20335        }
20336
20337        maxHeight = menuHeight;
20338        menuInnerHeight = menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert;
20339      } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
20340        for (var i = 0; i < this.options.size; i++) {
20341          if (this.selectpicker.current.data[i].type === 'divider') divLength++;
20342        }
20343
20344        menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
20345        menuInnerHeight = menuHeight - menuPadding.vert;
20346        maxHeight = menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
20347        minHeight = menuInnerMinHeight = '';
20348      }
20349
20350      if (this.options.dropdownAlignRight === 'auto') {
20351        this.$menu.toggleClass(classNames.MENURIGHT, this.sizeInfo.selectOffsetLeft > this.sizeInfo.selectOffsetRight && this.sizeInfo.selectOffsetRight < (this.sizeInfo.totalMenuWidth - selectWidth));
20352      }
20353
20354      this.$menu.css({
20355        'max-height': maxHeight + 'px',
20356        'overflow': 'hidden',
20357        'min-height': minHeight + 'px'
20358      });
20359
20360      this.$menuInner.css({
20361        'max-height': menuInnerHeight + 'px',
20362        'overflow-y': 'auto',
20363        'min-height': menuInnerMinHeight + 'px'
20364      });
20365
20366      this.sizeInfo.menuInnerHeight = menuInnerHeight;
20367
20368      if (this.selectpicker.current.data.length && this.selectpicker.current.data[this.selectpicker.current.data.length - 1].position > this.sizeInfo.menuInnerHeight) {
20369        this.sizeInfo.hasScrollBar = true;
20370        this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth + this.sizeInfo.scrollBarWidth;
20371
20372        this.$menu.css('min-width', this.sizeInfo.totalMenuWidth);
20373      }
20374
20375      if (this.dropdown && this.dropdown._popper) this.dropdown._popper.update();
20376    },
20377
20378    setSize: function (refresh) {
20379      this.liHeight(refresh);
20380
20381      if (this.options.header) this.$menu.css('padding-top', 0);
20382      if (this.options.size === false) return;
20383
20384      var that = this,
20385          $window = $(window),
20386          selectedIndex,
20387          offset = 0;
20388
20389      this.setMenuSize();
20390
20391      if (this.options.size === 'auto') {
20392        this.$searchbox
20393          .off('input.setMenuSize propertychange.setMenuSize')
20394          .on('input.setMenuSize propertychange.setMenuSize', function () {
20395            return that.setMenuSize();
20396          });
20397
20398        $window
20399          .off('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize')
20400          .on('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize', function () {
20401            return that.setMenuSize();
20402          });
20403      } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
20404        this.$searchbox.off('input.setMenuSize propertychange.setMenuSize');
20405        $window.off('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize');
20406      }
20407
20408      if (refresh) {
20409        offset = this.$menuInner[0].scrollTop;
20410      } else if (!that.multiple) {
20411        selectedIndex = that.selectpicker.main.map.newIndex[that.$element[0].selectedIndex];
20412
20413        if (typeof selectedIndex === 'number' && that.options.size !== false) {
20414          offset = that.sizeInfo.liHeight * selectedIndex;
20415          offset = offset - (that.sizeInfo.menuInnerHeight / 2) + (that.sizeInfo.liHeight / 2);
20416        }
20417      }
20418
20419      that.createView(false, offset);
20420    },
20421
20422    setWidth: function () {
20423      var that = this;
20424
20425      if (this.options.width === 'auto') {
20426        requestAnimationFrame(function () {
20427          that.$menu.css('min-width', '0');
20428          that.liHeight();
20429          that.setMenuSize();
20430
20431          // Get correct width if element is hidden
20432          var $selectClone = that.$newElement.clone().appendTo('body'),
20433              btnWidth = $selectClone.css('width', 'auto').children('button').outerWidth();
20434
20435          $selectClone.remove();
20436
20437          // Set width to whatever's larger, button title or longest option
20438          that.sizeInfo.selectWidth = Math.max(that.sizeInfo.totalMenuWidth, btnWidth);
20439          that.$newElement.css('width', that.sizeInfo.selectWidth + 'px');
20440        });
20441      } else if (this.options.width === 'fit') {
20442        // Remove inline min-width so width can be changed from 'auto'
20443        this.$menu.css('min-width', '');
20444        this.$newElement.css('width', '').addClass('fit-width');
20445      } else if (this.options.width) {
20446        // Remove inline min-width so width can be changed from 'auto'
20447        this.$menu.css('min-width', '');
20448        this.$newElement.css('width', this.options.width);
20449      } else {
20450        // Remove inline min-width/width so width can be changed
20451        this.$menu.css('min-width', '');
20452        this.$newElement.css('width', '');
20453      }
20454      // Remove fit-width class if width is changed programmatically
20455      if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
20456        this.$newElement.removeClass('fit-width');
20457      }
20458    },
20459
20460    selectPosition: function () {
20461      this.$bsContainer = $('<div class="bs-container" />');
20462
20463      var that = this,
20464          $container = $(this.options.container),
20465          pos,
20466          containerPos,
20467          actualHeight,
20468          getPlacement = function ($element) {
20469            var containerPosition = {},
20470                // fall back to dropdown's default display setting if display is not manually set
20471                display = that.options.display || (
20472                  // Bootstrap 3 doesn't have $.fn.dropdown.Constructor.Default
20473                  $.fn.dropdown.Constructor.Default ? $.fn.dropdown.Constructor.Default.display
20474                  : false
20475                );
20476
20477            that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass(classNames.DROPUP, $element.hasClass(classNames.DROPUP));
20478            pos = $element.offset();
20479
20480            if (!$container.is('body')) {
20481              containerPos = $container.offset();
20482              containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
20483              containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
20484            } else {
20485              containerPos = { top: 0, left: 0 };
20486            }
20487
20488            actualHeight = $element.hasClass(classNames.DROPUP) ? 0 : $element[0].offsetHeight;
20489
20490            // Bootstrap 4+ uses Popper for menu positioning
20491            if (version.major < 4 || display === 'static') {
20492              containerPosition.top = pos.top - containerPos.top + actualHeight;
20493              containerPosition.left = pos.left - containerPos.left;
20494            }
20495
20496            containerPosition.width = $element[0].offsetWidth;
20497
20498            that.$bsContainer.css(containerPosition);
20499          };
20500
20501      this.$button.on('click.bs.dropdown.data-api', function () {
20502        if (that.isDisabled()) {
20503          return;
20504        }
20505
20506        getPlacement(that.$newElement);
20507
20508        that.$bsContainer
20509          .appendTo(that.options.container)
20510          .toggleClass(classNames.SHOW, !that.$button.hasClass(classNames.SHOW))
20511          .append(that.$menu);
20512      });
20513
20514      $(window)
20515        .off('resize' + EVENT_KEY + '.' + this.selectId + ' scroll' + EVENT_KEY + '.' + this.selectId)
20516        .on('resize' + EVENT_KEY + '.' + this.selectId + ' scroll' + EVENT_KEY + '.' + this.selectId, function () {
20517          var isActive = that.$newElement.hasClass(classNames.SHOW);
20518
20519          if (isActive) getPlacement(that.$newElement);
20520        });
20521
20522      this.$element.on('hide' + EVENT_KEY, function () {
20523        that.$menu.data('height', that.$menu.height());
20524        that.$bsContainer.detach();
20525      });
20526    },
20527
20528    setOptionStatus: function () {
20529      var that = this,
20530          $selectOptions = this.$element.find('option');
20531
20532      that.noScroll = false;
20533
20534      if (that.selectpicker.view.visibleElements && that.selectpicker.view.visibleElements.length) {
20535        for (var i = 0; i < that.selectpicker.view.visibleElements.length; i++) {
20536          var index = that.selectpicker.current.map.originalIndex[i + that.selectpicker.view.position0], // faster than $(li).data('originalIndex')
20537              option = $selectOptions[index];
20538
20539          if (option) {
20540            var liIndex = this.selectpicker.main.map.newIndex[index],
20541                li = this.selectpicker.main.elements[liIndex];
20542
20543            that.setDisabled(
20544              index,
20545              option.disabled || (option.parentNode.tagName === 'OPTGROUP' && option.parentNode.disabled),
20546              liIndex,
20547              li
20548            );
20549
20550            that.setSelected(
20551              index,
20552              option.selected,
20553              liIndex,
20554              li
20555            );
20556          }
20557        }
20558      }
20559    },
20560
20561    /**
20562     * @param {number} index - the index of the option that is being changed
20563     * @param {boolean} selected - true if the option is being selected, false if being deselected
20564     */
20565    setSelected: function (index, selected, liIndex, li) {
20566      var activeIndexIsSet = this.activeIndex !== undefined,
20567          thisIsActive = this.activeIndex === index,
20568          prevActiveIndex,
20569          prevActive,
20570          a,
20571          // if current option is already active
20572          // OR
20573          // if the current option is being selected, it's NOT multiple, and
20574          // activeIndex is undefined:
20575          //  - when the menu is first being opened, OR
20576          //  - after a search has been performed, OR
20577          //  - when retainActive is false when selecting a new option (i.e. index of the newly selected option is not the same as the current activeIndex)
20578          keepActive = thisIsActive || (selected && !this.multiple && !activeIndexIsSet);
20579
20580      if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index];
20581      if (!li) li = this.selectpicker.main.elements[liIndex];
20582
20583      a = li.firstChild;
20584
20585      if (selected) {
20586        this.selectedIndex = index;
20587      }
20588
20589      li.classList.toggle('selected', selected);
20590      li.classList.toggle('active', keepActive);
20591
20592      if (keepActive) {
20593        this.selectpicker.view.currentActive = li;
20594        this.activeIndex = index;
20595      }
20596
20597      if (a) {
20598        a.classList.toggle('selected', selected);
20599        a.classList.toggle('active', keepActive);
20600        a.setAttribute('aria-selected', selected);
20601      }
20602
20603      if (!keepActive) {
20604        if (!activeIndexIsSet && selected && this.prevActiveIndex !== undefined) {
20605          prevActiveIndex = this.selectpicker.main.map.newIndex[this.prevActiveIndex];
20606          prevActive = this.selectpicker.main.elements[prevActiveIndex];
20607
20608          prevActive.classList.remove('active');
20609          if (prevActive.firstChild) {
20610            prevActive.firstChild.classList.remove('active');
20611          }
20612        }
20613      }
20614    },
20615
20616    /**
20617     * @param {number} index - the index of the option that is being disabled
20618     * @param {boolean} disabled - true if the option is being disabled, false if being enabled
20619     */
20620    setDisabled: function (index, disabled, liIndex, li) {
20621      var a;
20622
20623      if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index];
20624      if (!li) li = this.selectpicker.main.elements[liIndex];
20625
20626      a = li.firstChild;
20627
20628      li.classList.toggle(classNames.DISABLED, disabled);
20629
20630      if (a) {
20631        if (version.major === '4') a.classList.toggle(classNames.DISABLED, disabled);
20632
20633        a.setAttribute('aria-disabled', disabled);
20634
20635        if (disabled) {
20636          a.setAttribute('tabindex', -1);
20637        } else {
20638          a.setAttribute('tabindex', 0);
20639        }
20640      }
20641    },
20642
20643    isDisabled: function () {
20644      return this.$element[0].disabled;
20645    },
20646
20647    checkDisabled: function () {
20648      var that = this;
20649
20650      if (this.isDisabled()) {
20651        this.$newElement.addClass(classNames.DISABLED);
20652        this.$button.addClass(classNames.DISABLED).attr('tabindex', -1).attr('aria-disabled', true);
20653      } else {
20654        if (this.$button.hasClass(classNames.DISABLED)) {
20655          this.$newElement.removeClass(classNames.DISABLED);
20656          this.$button.removeClass(classNames.DISABLED).attr('aria-disabled', false);
20657        }
20658
20659        if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
20660          this.$button.removeAttr('tabindex');
20661        }
20662      }
20663
20664      this.$button.click(function () {
20665        return !that.isDisabled();
20666      });
20667    },
20668
20669    togglePlaceholder: function () {
20670      // much faster than calling $.val()
20671      var element = this.$element[0],
20672          selectedIndex = element.selectedIndex,
20673          nothingSelected = selectedIndex === -1;
20674
20675      if (!nothingSelected && !element.options[selectedIndex].value) nothingSelected = true;
20676
20677      this.$button.toggleClass('bs-placeholder', nothingSelected);
20678    },
20679
20680    tabIndex: function () {
20681      if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
20682        (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
20683        this.$element.data('tabindex', this.$element.attr('tabindex'));
20684        this.$button.attr('tabindex', this.$element.data('tabindex'));
20685      }
20686
20687      this.$element.attr('tabindex', -98);
20688    },
20689
20690    clickListener: function () {
20691      var that = this,
20692          $document = $(document);
20693
20694      $document.data('spaceSelect', false);
20695
20696      this.$button.on('keyup', function (e) {
20697        if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
20698          e.preventDefault();
20699          $document.data('spaceSelect', false);
20700        }
20701      });
20702
20703      this.$newElement.on('show.bs.dropdown', function () {
20704        if (version.major > 3 && !that.dropdown) {
20705          that.dropdown = that.$button.data('bs.dropdown');
20706          that.dropdown._menu = that.$menu[0];
20707        }
20708      });
20709
20710      this.$button.on('click.bs.dropdown.data-api', function () {
20711        if (!that.$newElement.hasClass(classNames.SHOW)) {
20712          that.setSize();
20713        }
20714      });
20715
20716      function setFocus () {
20717        if (that.options.liveSearch) {
20718          that.$searchbox.focus();
20719        } else {
20720          that.$menuInner.focus();
20721        }
20722      }
20723
20724      function checkPopperExists () {
20725        if (that.dropdown && that.dropdown._popper && that.dropdown._popper.state.isCreated) {
20726          setFocus();
20727        } else {
20728          requestAnimationFrame(checkPopperExists);
20729        }
20730      }
20731
20732      this.$element.on('shown' + EVENT_KEY, function () {
20733        if (that.$menuInner[0].scrollTop !== that.selectpicker.view.scrollTop) {
20734          that.$menuInner[0].scrollTop = that.selectpicker.view.scrollTop;
20735        }
20736
20737        if (version.major > 3) {
20738          requestAnimationFrame(checkPopperExists);
20739        } else {
20740          setFocus();
20741        }
20742      });
20743
20744      this.$menuInner.on('click', 'li a', function (e, retainActive) {
20745        var $this = $(this),
20746            position0 = that.isVirtual() ? that.selectpicker.view.position0 : 0,
20747            clickedIndex = that.selectpicker.current.map.originalIndex[$this.parent().index() + position0],
20748            prevValue = getSelectValues(that.$element[0]),
20749            prevIndex = that.$element.prop('selectedIndex'),
20750            triggerChange = true;
20751
20752        // Don't close on multi choice menu
20753        if (that.multiple && that.options.maxOptions !== 1) {
20754          e.stopPropagation();
20755        }
20756
20757        e.preventDefault();
20758
20759        // Don't run if the select is disabled
20760        if (!that.isDisabled() && !$this.parent().hasClass(classNames.DISABLED)) {
20761          var $options = that.$element.find('option'),
20762              $option = $options.eq(clickedIndex),
20763              state = $option.prop('selected'),
20764              $optgroup = $option.parent('optgroup'),
20765              $optgroupOptions = $optgroup.find('option'),
20766              maxOptions = that.options.maxOptions,
20767              maxOptionsGrp = $optgroup.data('maxOptions') || false;
20768
20769          if (clickedIndex === that.activeIndex) retainActive = true;
20770
20771          if (!retainActive) {
20772            that.prevActiveIndex = that.activeIndex;
20773            that.activeIndex = undefined;
20774          }
20775
20776          if (!that.multiple) { // Deselect all others if not multi select box
20777            $options.prop('selected', false);
20778            $option.prop('selected', true);
20779            that.setSelected(clickedIndex, true);
20780          } else { // Toggle the one we have chosen if we are multi select.
20781            $option.prop('selected', !state);
20782
20783            that.setSelected(clickedIndex, !state);
20784            $this.blur();
20785
20786            if (maxOptions !== false || maxOptionsGrp !== false) {
20787              var maxReached = maxOptions < $options.filter(':selected').length,
20788                  maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
20789
20790              if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
20791                if (maxOptions && maxOptions == 1) {
20792                  $options.prop('selected', false);
20793                  $option.prop('selected', true);
20794
20795                  for (var i = 0; i < $options.length; i++) {
20796                    that.setSelected(i, false);
20797                  }
20798
20799                  that.setSelected(clickedIndex, true);
20800                } else if (maxOptionsGrp && maxOptionsGrp == 1) {
20801                  $optgroup.find('option:selected').prop('selected', false);
20802                  $option.prop('selected', true);
20803
20804                  for (var i = 0; i < $optgroupOptions.length; i++) {
20805                    var option = $optgroupOptions[i];
20806                    that.setSelected($options.index(option), false);
20807                  }
20808
20809                  that.setSelected(clickedIndex, true);
20810                } else {
20811                  var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
20812                      maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
20813                      maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
20814                      maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
20815                      $notify = $('<div class="notify"></div>');
20816                  // If {var} is set in array, replace it
20817                  /** @deprecated */
20818                  if (maxOptionsArr[2]) {
20819                    maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
20820                    maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
20821                  }
20822
20823                  $option.prop('selected', false);
20824
20825                  that.$menu.append($notify);
20826
20827                  if (maxOptions && maxReached) {
20828                    $notify.append($('<div>' + maxTxt + '</div>'));
20829                    triggerChange = false;
20830                    that.$element.trigger('maxReached' + EVENT_KEY);
20831                  }
20832
20833                  if (maxOptionsGrp && maxReachedGrp) {
20834                    $notify.append($('<div>' + maxTxtGrp + '</div>'));
20835                    triggerChange = false;
20836                    that.$element.trigger('maxReachedGrp' + EVENT_KEY);
20837                  }
20838
20839                  setTimeout(function () {
20840                    that.setSelected(clickedIndex, false);
20841                  }, 10);
20842
20843                  $notify.delay(750).fadeOut(300, function () {
20844                    $(this).remove();
20845                  });
20846                }
20847              }
20848            }
20849          }
20850
20851          if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
20852            that.$button.focus();
20853          } else if (that.options.liveSearch) {
20854            that.$searchbox.focus();
20855          }
20856
20857          // Trigger select 'change'
20858          if (triggerChange) {
20859            if ((prevValue != getSelectValues(that.$element[0]) && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
20860              // $option.prop('selected') is current option state (selected/unselected). prevValue is the value of the select prior to being changed.
20861              changedArguments = [clickedIndex, $option.prop('selected'), prevValue];
20862              that.$element
20863                .triggerNative('change');
20864            }
20865          }
20866        }
20867      });
20868
20869      this.$menu.on('click', 'li.' + classNames.DISABLED + ' a, .' + classNames.POPOVERHEADER + ', .' + classNames.POPOVERHEADER + ' :not(.close)', function (e) {
20870        if (e.currentTarget == this) {
20871          e.preventDefault();
20872          e.stopPropagation();
20873          if (that.options.liveSearch && !$(e.target).hasClass('close')) {
20874            that.$searchbox.focus();
20875          } else {
20876            that.$button.focus();
20877          }
20878        }
20879      });
20880
20881      this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
20882        e.preventDefault();
20883        e.stopPropagation();
20884        if (that.options.liveSearch) {
20885          that.$searchbox.focus();
20886        } else {
20887          that.$button.focus();
20888        }
20889      });
20890
20891      this.$menu.on('click', '.' + classNames.POPOVERHEADER + ' .close', function () {
20892        that.$button.click();
20893      });
20894
20895      this.$searchbox.on('click', function (e) {
20896        e.stopPropagation();
20897      });
20898
20899      this.$menu.on('click', '.actions-btn', function (e) {
20900        if (that.options.liveSearch) {
20901          that.$searchbox.focus();
20902        } else {
20903          that.$button.focus();
20904        }
20905
20906        e.preventDefault();
20907        e.stopPropagation();
20908
20909        if ($(this).hasClass('bs-select-all')) {
20910          that.selectAll();
20911        } else {
20912          that.deselectAll();
20913        }
20914      });
20915
20916      this.$element.on({
20917        'change': function () {
20918          that.render();
20919          that.$element.trigger('changed' + EVENT_KEY, changedArguments);
20920          changedArguments = null;
20921        },
20922        'focus': function () {
20923          if (!that.options.mobile) that.$button.focus();
20924        }
20925      });
20926    },
20927
20928    liveSearchListener: function () {
20929      var that = this,
20930          noResults = document.createElement('li');
20931
20932      this.$button.on('click.bs.dropdown.data-api', function () {
20933        if (!!that.$searchbox.val()) {
20934          that.$searchbox.val('');
20935        }
20936      });
20937
20938      this.$searchbox.on('click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api', function (e) {
20939        e.stopPropagation();
20940      });
20941
20942      this.$searchbox.on('input propertychange', function () {
20943        var searchValue = that.$searchbox.val();
20944
20945        that.selectpicker.search.map.newIndex = {};
20946        that.selectpicker.search.map.originalIndex = {};
20947        that.selectpicker.search.elements = [];
20948        that.selectpicker.search.data = [];
20949
20950        if (searchValue) {
20951          var i,
20952              searchMatch = [],
20953              q = searchValue.toUpperCase(),
20954              cache = {},
20955              cacheArr = [],
20956              searchStyle = that._searchStyle(),
20957              normalizeSearch = that.options.liveSearchNormalize;
20958
20959          if (normalizeSearch) q = normalizeToBase(q);
20960
20961          that._$lisSelected = that.$menuInner.find('.selected');
20962
20963          for (var i = 0; i < that.selectpicker.main.data.length; i++) {
20964            var li = that.selectpicker.main.data[i];
20965
20966            if (!cache[i]) {
20967              cache[i] = stringSearch(li, q, searchStyle, normalizeSearch);
20968            }
20969
20970            if (cache[i] && li.headerIndex !== undefined && cacheArr.indexOf(li.headerIndex) === -1) {
20971              if (li.headerIndex > 0) {
20972                cache[li.headerIndex - 1] = true;
20973                cacheArr.push(li.headerIndex - 1);
20974              }
20975
20976              cache[li.headerIndex] = true;
20977              cacheArr.push(li.headerIndex);
20978
20979              cache[li.lastIndex + 1] = true;
20980            }
20981
20982            if (cache[i] && li.type !== 'optgroup-label') cacheArr.push(i);
20983          }
20984
20985          for (var i = 0, cacheLen = cacheArr.length; i < cacheLen; i++) {
20986            var index = cacheArr[i],
20987                prevIndex = cacheArr[i - 1],
20988                li = that.selectpicker.main.data[index],
20989                liPrev = that.selectpicker.main.data[prevIndex];
20990
20991            if (li.type !== 'divider' || (li.type === 'divider' && liPrev && liPrev.type !== 'divider' && cacheLen - 1 !== i)) {
20992              that.selectpicker.search.data.push(li);
20993              searchMatch.push(that.selectpicker.main.elements[index]);
20994
20995              if (li.hasOwnProperty('originalIndex')) {
20996                that.selectpicker.search.map.newIndex[li.originalIndex] = searchMatch.length - 1;
20997                that.selectpicker.search.map.originalIndex[searchMatch.length - 1] = li.originalIndex;
20998              }
20999            }
21000          }
21001
21002          that.activeIndex = undefined;
21003          that.noScroll = true;
21004          that.$menuInner.scrollTop(0);
21005          that.selectpicker.search.elements = searchMatch;
21006          that.createView(true);
21007
21008          if (!searchMatch.length) {
21009            noResults.className = 'no-results';
21010            noResults.innerHTML = that.options.noneResultsText.replace('{0}', '"' + htmlEscape(searchValue) + '"');
21011            that.$menuInner[0].firstChild.appendChild(noResults);
21012          }
21013        } else {
21014          that.$menuInner.scrollTop(0);
21015          that.createView(false);
21016        }
21017      });
21018    },
21019
21020    _searchStyle: function () {
21021      return this.options.liveSearchStyle || 'contains';
21022    },
21023
21024    val: function (value) {
21025      if (typeof value !== 'undefined') {
21026        this.$element
21027          .val(value)
21028          .triggerNative('change');
21029
21030        return this.$element;
21031      } else {
21032        return this.$element.val();
21033      }
21034    },
21035
21036    changeAll: function (status) {
21037      if (!this.multiple) return;
21038      if (typeof status === 'undefined') status = true;
21039
21040      var $selectOptions = this.$element.find('option'),
21041          previousSelected = 0,
21042          currentSelected = 0,
21043          prevValue = getSelectValues(this.$element[0]);
21044
21045      this.$element.addClass('bs-select-hidden');
21046
21047      for (var i = 0; i < this.selectpicker.current.elements.length; i++) {
21048        var liData = this.selectpicker.current.data[i],
21049            index = this.selectpicker.current.map.originalIndex[i], // faster than $(li).data('originalIndex')
21050            option = $selectOptions[index];
21051
21052        if (option && !option.disabled && liData.type !== 'divider') {
21053          if (option.selected) previousSelected++;
21054          option.selected = status;
21055          if (option.selected) currentSelected++;
21056        }
21057      }
21058
21059      this.$element.removeClass('bs-select-hidden');
21060
21061      if (previousSelected === currentSelected) return;
21062
21063      this.setOptionStatus();
21064
21065      this.togglePlaceholder();
21066
21067      changedArguments = [null, null, prevValue];
21068
21069      this.$element
21070        .triggerNative('change');
21071    },
21072
21073    selectAll: function () {
21074      return this.changeAll(true);
21075    },
21076
21077    deselectAll: function () {
21078      return this.changeAll(false);
21079    },
21080
21081    toggle: function (e) {
21082      e = e || window.event;
21083
21084      if (e) e.stopPropagation();
21085
21086      this.$button.trigger('click.bs.dropdown.data-api');
21087    },
21088
21089    keydown: function (e) {
21090      var $this = $(this),
21091          isToggle = $this.hasClass('dropdown-toggle'),
21092          $parent = isToggle ? $this.closest('.dropdown') : $this.closest(Selector.MENU),
21093          that = $parent.data('this'),
21094          $items = that.findLis(),
21095          index,
21096          isActive,
21097          liActive,
21098          activeLi,
21099          offset,
21100          updateScroll = false,
21101          downOnTab = e.which === keyCodes.TAB && !isToggle && !that.options.selectOnTab,
21102          isArrowKey = REGEXP_ARROW.test(e.which) || downOnTab,
21103          scrollTop = that.$menuInner[0].scrollTop,
21104          isVirtual = that.isVirtual(),
21105          position0 = isVirtual === true ? that.selectpicker.view.position0 : 0;
21106
21107      isActive = that.$newElement.hasClass(classNames.SHOW);
21108
21109      if (
21110        !isActive &&
21111        (
21112          isArrowKey ||
21113          (e.which >= 48 && e.which <= 57) ||
21114          (e.which >= 96 && e.which <= 105) ||
21115          (e.which >= 65 && e.which <= 90)
21116        )
21117      ) {
21118        that.$button.trigger('click.bs.dropdown.data-api');
21119      }
21120
21121      if (e.which === keyCodes.ESCAPE && isActive) {
21122        e.preventDefault();
21123        that.$button.trigger('click.bs.dropdown.data-api').focus();
21124      }
21125
21126      if (isArrowKey) { // if up or down
21127        if (!$items.length) return;
21128
21129        // $items.index/.filter is too slow with a large list and no virtual scroll
21130        index = isVirtual === true ? $items.index($items.filter('.active')) : that.selectpicker.current.map.newIndex[that.activeIndex];
21131
21132        if (index === undefined) index = -1;
21133
21134        if (index !== -1) {
21135          liActive = that.selectpicker.current.elements[index + position0];
21136          liActive.classList.remove('active');
21137          if (liActive.firstChild) liActive.firstChild.classList.remove('active');
21138        }
21139
21140        if (e.which === keyCodes.ARROW_UP) { // up
21141          if (index !== -1) index--;
21142          if (index + position0 < 0) index += $items.length;
21143
21144          if (!that.selectpicker.view.canHighlight[index + position0]) {
21145            index = that.selectpicker.view.canHighlight.slice(0, index + position0).lastIndexOf(true) - position0;
21146            if (index === -1) index = $items.length - 1;
21147          }
21148        } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
21149          index++;
21150          if (index + position0 >
vendor: 10,123 bytes, lines 21150-21460
21150= that.selectpicker.view.canHighlight.length) index = 0;
21151
21152          if (!that.selectpicker.view.canHighlight[index + position0]) {
21153            index = index + 1 + that.selectpicker.view.canHighlight.slice(index + position0 + 1).indexOf(true);
21154          }
21155        }
21156
21157        e.preventDefault();
21158
21159        var liActiveIndex = position0 + index;
21160
21161        if (e.which === keyCodes.ARROW_UP) { // up
21162          // scroll to bottom and highlight last option
21163          if (position0 === 0 && index === $items.length - 1) {
21164            that.$menuInner[0].scrollTop = that.$menuInner[0].scrollHeight;
21165
21166            liActiveIndex = that.selectpicker.current.elements.length - 1;
21167          } else {
21168            activeLi = that.selectpicker.current.data[liActiveIndex];
21169            offset = activeLi.position - activeLi.height;
21170
21171            updateScroll = offset < scrollTop;
21172          }
21173        } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
21174          // scroll to top and highlight first option
21175          if (index === 0) {
21176            that.$menuInner[0].scrollTop = 0;
21177
21178            liActiveIndex = 0;
21179          } else {
21180            activeLi = that.selectpicker.current.data[liActiveIndex];
21181            offset = activeLi.position - that.sizeInfo.menuInnerHeight;
21182
21183            updateScroll = offset > scrollTop;
21184          }
21185        }
21186
21187        liActive = that.selectpicker.current.elements[liActiveIndex];
21188
21189        if (liActive) {
21190          liActive.classList.add('active');
21191          if (liActive.firstChild) liActive.firstChild.classList.add('active');
21192        }
21193
21194        that.activeIndex = that.selectpicker.current.map.originalIndex[liActiveIndex];
21195
21196        that.selectpicker.view.currentActive = liActive;
21197
21198        if (updateScroll) that.$menuInner[0].scrollTop = offset;
21199
21200        if (that.options.liveSearch) {
21201          that.$searchbox.focus();
21202        } else {
21203          $this.focus();
21204        }
21205      } else if (
21206        (!$this.is('input') && !REGEXP_TAB_OR_ESCAPE.test(e.which)) ||
21207        (e.which === keyCodes.SPACE && that.selectpicker.keydown.keyHistory)
21208      ) {
21209        var searchMatch,
21210            matches = [],
21211            keyHistory;
21212
21213        e.preventDefault();
21214
21215        that.selectpicker.keydown.keyHistory += keyCodeMap[e.which];
21216
21217        if (that.selectpicker.keydown.resetKeyHistory.cancel) clearTimeout(that.selectpicker.keydown.resetKeyHistory.cancel);
21218        that.selectpicker.keydown.resetKeyHistory.cancel = that.selectpicker.keydown.resetKeyHistory.start();
21219
21220        keyHistory = that.selectpicker.keydown.keyHistory;
21221
21222        // if all letters are the same, set keyHistory to just the first character when searching
21223        if (/^(.)\1+$/.test(keyHistory)) {
21224          keyHistory = keyHistory.charAt(0);
21225        }
21226
21227        // find matches
21228        for (var i = 0; i < that.selectpicker.current.data.length; i++) {
21229          var li = that.selectpicker.current.data[i],
21230              hasMatch;
21231
21232          hasMatch = stringSearch(li, keyHistory, 'startsWith', true);
21233
21234          if (hasMatch && that.selectpicker.view.canHighlight[i]) {
21235            li.index = i;
21236            matches.push(li.originalIndex);
21237          }
21238        }
21239
21240        if (matches.length) {
21241          var matchIndex = 0;
21242
21243          $items.removeClass('active').find('a').removeClass('active');
21244
21245          // either only one key has been pressed or they are all the same key
21246          if (keyHistory.length === 1) {
21247            matchIndex = matches.indexOf(that.activeIndex);
21248
21249            if (matchIndex === -1 || matchIndex === matches.length - 1) {
21250              matchIndex = 0;
21251            } else {
21252              matchIndex++;
21253            }
21254          }
21255
21256          searchMatch = that.selectpicker.current.map.newIndex[matches[matchIndex]];
21257
21258          activeLi = that.selectpicker.current.data[searchMatch];
21259
21260          if (scrollTop - activeLi.position > 0) {
21261            offset = activeLi.position - activeLi.height;
21262            updateScroll = true;
21263          } else {
21264            offset = activeLi.position - that.sizeInfo.menuInnerHeight;
21265            // if the option is already visible at the current scroll position, just keep it the same
21266            updateScroll = activeLi.position > scrollTop + that.sizeInfo.menuInnerHeight;
21267          }
21268
21269          liActive = that.selectpicker.current.elements[searchMatch];
21270          liActive.classList.add('active');
21271          if (liActive.firstChild) liActive.firstChild.classList.add('active');
21272          that.activeIndex = matches[matchIndex];
21273
21274          liActive.firstChild.focus();
21275
21276          if (updateScroll) that.$menuInner[0].scrollTop = offset;
21277
21278          $this.focus();
21279        }
21280      }
21281
21282      // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
21283      if (
21284        isActive &&
21285        (
21286          (e.which === keyCodes.SPACE && !that.selectpicker.keydown.keyHistory) ||
21287          e.which === keyCodes.ENTER ||
21288          (e.which === keyCodes.TAB && that.options.selectOnTab)
21289        )
21290      ) {
21291        if (e.which !== keyCodes.SPACE) e.preventDefault();
21292
21293        if (!that.options.liveSearch || e.which !== keyCodes.SPACE) {
21294          that.$menuInner.find('.active a').trigger('click', true); // retain active class
21295          $this.focus();
21296
21297          if (!that.options.liveSearch) {
21298            // Prevent screen from scrolling if the user hits the spacebar
21299            e.preventDefault();
21300            // Fixes spacebar selection of dropdown items in FF & IE
21301            $(document).data('spaceSelect', true);
21302          }
21303        }
21304      }
21305    },
21306
21307    mobile: function () {
21308      this.$element.addClass('mobile-device');
21309    },
21310
21311    refresh: function () {
21312      // update options if data attributes have been changed
21313      var config = $.extend({}, this.options, this.$element.data());
21314      this.options = config;
21315
21316      this.selectpicker.main.map.newIndex = {};
21317      this.selectpicker.main.map.originalIndex = {};
21318      this.createLi();
21319      this.checkDisabled();
21320      this.render();
21321      this.setStyle();
21322      this.setWidth();
21323
21324      this.setSize(true);
21325
21326      this.$element.trigger('refreshed' + EVENT_KEY);
21327    },
21328
21329    hide: function () {
21330      this.$newElement.hide();
21331    },
21332
21333    show: function () {
21334      this.$newElement.show();
21335    },
21336
21337    remove: function () {
21338      this.$newElement.remove();
21339      this.$element.remove();
21340    },
21341
21342    destroy: function () {
21343      this.$newElement.before(this.$element).remove();
21344
21345      if (this.$bsContainer) {
21346        this.$bsContainer.remove();
21347      } else {
21348        this.$menu.remove();
21349      }
21350
21351      this.$element
21352        .off(EVENT_KEY)
21353        .removeData('selectpicker')
21354        .removeClass('bs-select-hidden selectpicker');
21355
21356      $(window).off(EVENT_KEY + '.' + this.selectId);
21357    }
21358  };
21359
21360  // SELECTPICKER PLUGIN DEFINITION
21361  // ==============================
21362  function Plugin (option) {
21363    // get the args of the outer function..
21364    var args = arguments;
21365    // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
21366    // to get lost/corrupted in android 2.3 and IE9 #715 #775
21367    var _option = option;
21368
21369    [].shift.apply(args);
21370
21371    // if the version was not set successfully
21372    if (!version.success) {
21373      // try to retreive it again
21374      try {
21375        version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
21376      } catch (err) {
21377        // fall back to use BootstrapVersion
21378        version.full = Selectpicker.BootstrapVersion.split(' ')[0].split('.');
21379      }
21380
21381      version.major = version.full[0];
21382      version.success = true;
21383
21384      if (version.major === '4') {
21385        classNames.DIVIDER = 'dropdown-divider';
21386        classNames.SHOW = 'show';
21387        classNames.BUTTONCLASS = 'btn-light';
21388        Selectpicker.DEFAULTS.style = classNames.BUTTONCLASS = 'btn-light';
21389        classNames.POPOVERHEADER = 'popover-header';
21390      }
21391    }
21392
21393    var value;
21394    var chain = this.each(function () {
21395      var $this = $(this);
21396      if ($this.is('select')) {
21397        var data = $this.data('selectpicker'),
21398            options = typeof _option == 'object' && _option;
21399
21400        if (!data) {
21401          var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
21402          config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
21403          $this.data('selectpicker', (data = new Selectpicker(this, config)));
21404        } else if (options) {
21405          for (var i in options) {
21406            if (options.hasOwnProperty(i)) {
21407              data.options[i] = options[i];
21408            }
21409          }
21410        }
21411
21412        if (typeof _option == 'string') {
21413          if (data[_option] instanceof Function) {
21414            value = data[_option].apply(data, args);
21415          } else {
21416            value = data.options[_option];
21417          }
21418        }
21419      }
21420    });
21421
21422    if (typeof value !== 'undefined') {
21423      // noinspection JSUnusedAssignment
21424      return value;
21425    } else {
21426      return chain;
21427    }
21428  }
21429
21430  var old = $.fn.selectpicker;
21431  $.fn.selectpicker = Plugin;
21432  $.fn.selectpicker.Constructor = Selectpicker;
21433
21434  // SELECTPICKER NO CONFLICT
21435  // ========================
21436  $.fn.selectpicker.noConflict = function () {
21437    $.fn.selectpicker = old;
21438    return this;
21439  };
21440
21441  $(document)
21442    .off('keydown.bs.dropdown.data-api')
21443    .on('keydown' + EVENT_KEY, '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input', Selectpicker.prototype.keydown)
21444    .on('focusin.modal', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input', function (e) {
21445      e.stopPropagation();
21446    });
21447
21448  // SELECTPICKER DATA-API
21449  // =====================
21450  $(window).on('load' + EVENT_KEY + '.data-api', function () {
21451    $('.selectpicker').each(function () {
21452      var $selectpicker = $(this);
21453      Plugin.call($selectpicker, $selectpicker.data());
21454    })
21455  });
21456})(jQuery);
21457
21458
21459}));
21460
vendor: 32,123 bytes, lines 21461-22346
21461/*!
21462 * typeahead.js 0.11.1
21463 * https://github.com/twitter/typeahead.js
21464 * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
21465 */
21466
21467(function(root, factory) {
21468    if (typeof define === "function" && define.amd) {
21469        define("bloodhound", [ "jquery" ], function(a0) {
21470            return root["Bloodhound"] = factory(a0);
21471        });
21472    } else if (typeof exports === "object") {
21473        module.exports = factory(require("jquery"));
21474    } else {
21475        root["Bloodhound"] = factory(jQuery);
21476    }
21477})(this, function($) {
21478    var _ = function() {
21479        "use strict";
21480        return {
21481            isMsie: function() {
21482                return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
21483            },
21484            isBlankString: function(str) {
21485                return !str || /^\s*$/.test(str);
21486            },
21487            escapeRegExChars: function(str) {
21488                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
21489            },
21490            isString: function(obj) {
21491                return typeof obj === "string";
21492            },
21493            isNumber: function(obj) {
21494                return typeof obj === "number";
21495            },
21496            isArray: $.isArray,
21497            isFunction: $.isFunction,
21498            isObject: $.isPlainObject,
21499            isUndefined: function(obj) {
21500                return typeof obj === "undefined";
21501            },
21502            isElement: function(obj) {
21503                return !!(obj && obj.nodeType === 1);
21504            },
21505            isJQuery: function(obj) {
21506                return obj instanceof $;
21507            },
21508            toStr: function toStr(s) {
21509                return _.isUndefined(s) || s === null ? "" : s + "";
21510            },
21511            bind: $.proxy,
21512            each: function(collection, cb) {
21513                $.each(collection, reverseArgs);
21514                function reverseArgs(index, value) {
21515                    return cb(value, index);
21516                }
21517            },
21518            map: $.map,
21519            filter: $.grep,
21520            every: function(obj, test) {
21521                var result = true;
21522                if (!obj) {
21523                    return result;
21524                }
21525                $.each(obj, function(key, val) {
21526                    if (!(result = test.call(null, val, key, obj))) {
21527                        return false;
21528                    }
21529                });
21530                return !!result;
21531            },
21532            some: function(obj, test) {
21533                var result = false;
21534                if (!obj) {
21535                    return result;
21536                }
21537                $.each(obj, function(key, val) {
21538                    if (result = test.call(null, val, key, obj)) {
21539                        return false;
21540                    }
21541                });
21542                return !!result;
21543            },
21544            mixin: $.extend,
21545            identity: function(x) {
21546                return x;
21547            },
21548            clone: function(obj) {
21549                return $.extend(true, {}, obj);
21550            },
21551            getIdGenerator: function() {
21552                var counter = 0;
21553                return function() {
21554                    return counter++;
21555                };
21556            },
21557            templatify: function templatify(obj) {
21558                return $.isFunction(obj) ? obj : template;
21559                function template() {
21560                    return String(obj);
21561                }
21562            },
21563            defer: function(fn) {
21564                setTimeout(fn, 0);
21565            },
21566            debounce: function(func, wait, immediate) {
21567                var timeout, result;
21568                return function() {
21569                    var context = this, args = arguments, later, callNow;
21570                    later = function() {
21571                        timeout = null;
21572                        if (!immediate) {
21573                            result = func.apply(context, args);
21574                        }
21575                    };
21576                    callNow = immediate && !timeout;
21577                    clearTimeout(timeout);
21578                    timeout = setTimeout(later, wait);
21579                    if (callNow) {
21580                        result = func.apply(context, args);
21581                    }
21582                    return result;
21583                };
21584            },
21585            throttle: function(func, wait) {
21586                var context, args, timeout, result, previous, later;
21587                previous = 0;
21588                later = function() {
21589                    previous = new Date();
21590                    timeout = null;
21591                    result = func.apply(context, args);
21592                };
21593                return function() {
21594                    var now = new Date(), remaining = wait - (now - previous);
21595                    context = this;
21596                    args = arguments;
21597                    if (remaining <= 0) {
21598                        clearTimeout(timeout);
21599                        timeout = null;
21600                        previous = now;
21601                        result = func.apply(context, args);
21602                    } else if (!timeout) {
21603                        timeout = setTimeout(later, remaining);
21604                    }
21605                    return result;
21606                };
21607            },
21608            stringify: function(val) {
21609                return _.isString(val) ? val : JSON.stringify(val);
21610            },
21611            noop: function() {}
21612        };
21613    }();
21614    var VERSION = "0.11.1";
21615    var tokenizers = function() {
21616        "use strict";
21617        return {
21618            nonword: nonword,
21619            whitespace: whitespace,
21620            obj: {
21621                nonword: getObjTokenizer(nonword),
21622                whitespace: getObjTokenizer(whitespace)
21623            }
21624        };
21625        function whitespace(str) {
21626            str = _.toStr(str);
21627            return str ? str.split(/\s+/) : [];
21628        }
21629        function nonword(str) {
21630            str = _.toStr(str);
21631            return str ? str.split(/\W+/) : [];
21632        }
21633        function getObjTokenizer(tokenizer) {
21634            return function setKey(keys) {
21635                keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
21636                return function tokenize(o) {
21637                    var tokens = [];
21638                    _.each(keys, function(k) {
21639                        tokens = tokens.concat(tokenizer(_.toStr(o[k])));
21640                    });
21641                    return tokens;
21642                };
21643            };
21644        }
21645    }();
21646    var LruCache = function() {
21647        "use strict";
21648        function LruCache(maxSize) {
21649            this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
21650            this.reset();
21651            if (this.maxSize <= 0) {
21652                this.set = this.get = $.noop;
21653            }
21654        }
21655        _.mixin(LruCache.prototype, {
21656            set: function set(key, val) {
21657                var tailItem = this.list.tail, node;
21658                if (this.size >= this.maxSize) {
21659                    this.list.remove(tailItem);
21660                    delete this.hash[tailItem.key];
21661                    this.size--;
21662                }
21663                if (node = this.hash[key]) {
21664                    node.val = val;
21665                    this.list.moveToFront(node);
21666                } else {
21667                    node = new Node(key, val);
21668                    this.list.add(node);
21669                    this.hash[key] = node;
21670                    this.size++;
21671                }
21672            },
21673            get: function get(key) {
21674                var node = this.hash[key];
21675                if (node) {
21676                    this.list.moveToFront(node);
21677                    return node.val;
21678                }
21679            },
21680            reset: function reset() {
21681                this.size = 0;
21682                this.hash = {};
21683                this.list = new List();
21684            }
21685        });
21686        function List() {
21687            this.head = this.tail = null;
21688        }
21689        _.mixin(List.prototype, {
21690            add: function add(node) {
21691                if (this.head) {
21692                    node.next = this.head;
21693                    this.head.prev = node;
21694                }
21695                this.head = node;
21696                this.tail = this.tail || node;
21697            },
21698            remove: function remove(node) {
21699                node.prev ? node.prev.next = node.next : this.head = node.next;
21700                node.next ? node.next.prev = node.prev : this.tail = node.prev;
21701            },
21702            moveToFront: function(node) {
21703                this.remove(node);
21704                this.add(node);
21705            }
21706        });
21707        function Node(key, val) {
21708            this.key = key;
21709            this.val = val;
21710            this.prev = this.next = null;
21711        }
21712        return LruCache;
21713    }();
21714    var PersistentStorage = function() {
21715        "use strict";
21716        var LOCAL_STORAGE;
21717        try {
21718            LOCAL_STORAGE = window.localStorage;
21719            LOCAL_STORAGE.setItem("~~~", "!");
21720            LOCAL_STORAGE.removeItem("~~~");
21721        } catch (err) {
21722            LOCAL_STORAGE = null;
21723        }
21724        function PersistentStorage(namespace, override) {
21725            this.prefix = [ "__", namespace, "__" ].join("");
21726            this.ttlKey = "__ttl__";
21727            this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
21728            this.ls = override || LOCAL_STORAGE;
21729            !this.ls && this._noop();
21730        }
21731        _.mixin(PersistentStorage.prototype, {
21732            _prefix: function(key) {
21733                return this.prefix + key;
21734            },
21735            _ttlKey: function(key) {
21736                return this._prefix(key) + this.ttlKey;
21737            },
21738            _noop: function() {
21739                this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
21740            },
21741            _safeSet: function(key, val) {
21742                try {
21743                    this.ls.setItem(key, val);
21744                } catch (err) {
21745                    if (err.name === "QuotaExceededError") {
21746                        this.clear();
21747                        this._noop();
21748                    }
21749                }
21750            },
21751            get: function(key) {
21752                if (this.isExpired(key)) {
21753                    this.remove(key);
21754                }
21755                return decode(this.ls.getItem(this._prefix(key)));
21756            },
21757            set: function(key, val, ttl) {
21758                if (_.isNumber(ttl)) {
21759                    this._safeSet(this._ttlKey(key), encode(now() + ttl));
21760                } else {
21761                    this.ls.removeItem(this._ttlKey(key));
21762                }
21763                return this._safeSet(this._prefix(key), encode(val));
21764            },
21765            remove: function(key) {
21766                this.ls.removeItem(this._ttlKey(key));
21767                this.ls.removeItem(this._prefix(key));
21768                return this;
21769            },
21770            clear: function() {
21771                var i, keys = gatherMatchingKeys(this.keyMatcher);
21772                for (i = keys.length; i--; ) {
21773                    this.remove(keys[i]);
21774                }
21775                return this;
21776            },
21777            isExpired: function(key) {
21778                var ttl = decode(this.ls.getItem(this._ttlKey(key)));
21779                return _.isNumber(ttl) && now() > ttl ? true : false;
21780            }
21781        });
21782        return PersistentStorage;
21783        function now() {
21784            return new Date().getTime();
21785        }
21786        function encode(val) {
21787            return JSON.stringify(_.isUndefined(val) ? null : val);
21788        }
21789        function decode(val) {
21790            return $.parseJSON(val);
21791        }
21792        function gatherMatchingKeys(keyMatcher) {
21793            var i, key, keys = [], len = LOCAL_STORAGE.length;
21794            for (i = 0; i < len; i++) {
21795                if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
21796                    keys.push(key.replace(keyMatcher, ""));
21797                }
21798            }
21799            return keys;
21800        }
21801    }();
21802    var Transport = function() {
21803        "use strict";
21804        var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
21805        function Transport(o) {
21806            o = o || {};
21807            this.cancelled = false;
21808            this.lastReq = null;
21809            this._send = o.transport;
21810            this._get = o.limiter ? o.limiter(this._get) : this._get;
21811            this._cache = o.cache === false ? new LruCache(0) : sharedCache;
21812        }
21813        Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
21814            maxPendingRequests = num;
21815        };
21816        Transport.resetCache = function resetCache() {
21817            sharedCache.reset();
21818        };
21819        _.mixin(Transport.prototype, {
21820            _fingerprint: function fingerprint(o) {
21821                o = o || {};
21822                return o.url + o.type + $.param(o.data || {});
21823            },
21824            _get: function(o, cb) {
21825                var that = this, fingerprint, jqXhr;
21826                fingerprint = this._fingerprint(o);
21827                if (this.cancelled || fingerprint !== this.lastReq) {
21828                    return;
21829                }
21830                if (jqXhr = pendingRequests[fingerprint]) {
21831                    jqXhr.done(done).fail(fail);
21832                } else if (pendingRequestsCount < maxPendingRequests) {
21833                    pendingRequestsCount++;
21834                    pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
21835                } else {
21836                    this.onDeckRequestArgs = [].slice.call(arguments, 0);
21837                }
21838                function done(resp) {
21839                    cb(null, resp);
21840                    that._cache.set(fingerprint, resp);
21841                }
21842                function fail() {
21843                    cb(true);
21844                }
21845                function always() {
21846                    pendingRequestsCount--;
21847                    delete pendingRequests[fingerprint];
21848                    if (that.onDeckRequestArgs) {
21849                        that._get.apply(that, that.onDeckRequestArgs);
21850                        that.onDeckRequestArgs = null;
21851                    }
21852                }
21853            },
21854            get: function(o, cb) {
21855                var resp, fingerprint;
21856                cb = cb || $.noop;
21857                o = _.isString(o) ? {
21858                    url: o
21859                } : o || {};
21860                fingerprint = this._fingerprint(o);
21861                this.cancelled = false;
21862                this.lastReq = fingerprint;
21863                if (resp = this._cache.get(fingerprint)) {
21864                    cb(null, resp);
21865                } else {
21866                    this._get(o, cb);
21867                }
21868            },
21869            cancel: function() {
21870                this.cancelled = true;
21871            }
21872        });
21873        return Transport;
21874    }();
21875    var SearchIndex = window.SearchIndex = function() {
21876        "use strict";
21877        var CHILDREN = "c", IDS = "i";
21878        function SearchIndex(o) {
21879            o = o || {};
21880            if (!o.datumTokenizer || !o.queryTokenizer) {
21881                $.error("datumTokenizer and queryTokenizer are both required");
21882            }
21883            this.identify = o.identify || _.stringify;
21884            this.datumTokenizer = o.datumTokenizer;
21885            this.queryTokenizer = o.queryTokenizer;
21886            this.reset();
21887        }
21888        _.mixin(SearchIndex.prototype, {
21889            bootstrap: function bootstrap(o) {
21890                this.datums = o.datums;
21891                this.trie = o.trie;
21892            },
21893            add: function(data) {
21894                var that = this;
21895                data = _.isArray(data) ? data : [ data ];
21896                _.each(data, function(datum) {
21897                    var id, tokens;
21898                    that.datums[id = that.identify(datum)] = datum;
21899                    tokens = normalizeTokens(that.datumTokenizer(datum));
21900                    _.each(tokens, function(token) {
21901                        var node, chars, ch;
21902                        node = that.trie;
21903                        chars = token.split("");
21904                        while (ch = chars.shift()) {
21905                            node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
21906                            node[IDS].push(id);
21907                        }
21908                    });
21909                });
21910            },
21911            get: function get(ids) {
21912                var that = this;
21913                return _.map(ids, function(id) {
21914                    return that.datums[id];
21915                });
21916            },
21917            search: function search(query) {
21918                var that = this, tokens, matches;
21919                tokens = normalizeTokens(this.queryTokenizer(query));
21920                _.each(tokens, function(token) {
21921                    var node, chars, ch, ids;
21922                    if (matches && matches.length === 0) {
21923                        return false;
21924                    }
21925                    node = that.trie;
21926                    chars = token.split("");
21927                    while (node && (ch = chars.shift())) {
21928                        node = node[CHILDREN][ch];
21929                    }
21930                    if (node && chars.length === 0) {
21931                        ids = node[IDS].slice(0);
21932                        matches = matches ? getIntersection(matches, ids) : ids;
21933                    } else {
21934                        matches = [];
21935                        return false;
21936                    }
21937                });
21938                return matches ? _.map(unique(matches), function(id) {
21939                    return that.datums[id];
21940                }) : [];
21941            },
21942            all: function all() {
21943                var values = [];
21944                for (var key in this.datums) {
21945                    values.push(this.datums[key]);
21946                }
21947                return values;
21948            },
21949            reset: function reset() {
21950                this.datums = {};
21951                this.trie = newNode();
21952            },
21953            serialize: function serialize() {
21954                return {
21955                    datums: this.datums,
21956                    trie: this.trie
21957                };
21958            }
21959        });
21960        return SearchIndex;
21961        function normalizeTokens(tokens) {
21962            tokens = _.filter(tokens, function(token) {
21963                return !!token;
21964            });
21965            tokens = _.map(tokens, function(token) {
21966                return token.toLowerCase();
21967            });
21968            return tokens;
21969        }
21970        function newNode() {
21971            var node = {};
21972            node[IDS] = [];
21973            node[CHILDREN] = {};
21974            return node;
21975        }
21976        function unique(array) {
21977            var seen = {}, uniques = [];
21978            for (var i = 0, len = array.length; i < len; i++) {
21979                if (!seen[array[i]]) {
21980                    seen[array[i]] = true;
21981                    uniques.push(array[i]);
21982                }
21983            }
21984            return uniques;
21985        }
21986        function getIntersection(arrayA, arrayB) {
21987            var ai = 0, bi = 0, intersection = [];
21988            arrayA = arrayA.sort();
21989            arrayB = arrayB.sort();
21990            var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
21991            while (ai < lenArrayA && bi < lenArrayB) {
21992                if (arrayA[ai] < arrayB[bi]) {
21993                    ai++;
21994                } else if (arrayA[ai] > arrayB[bi]) {
21995                    bi++;
21996                } else {
21997                    intersection.push(arrayA[ai]);
21998                    ai++;
21999                    bi++;
22000                }
22001            }
22002            return intersection;
22003        }
22004    }();
22005    var Prefetch = function() {
22006        "use strict";
22007        var keys;
22008        keys = {
22009            data: "data",
22010            protocol: "protocol",
22011            thumbprint: "thumbprint"
22012        };
22013        function Prefetch(o) {
22014            this.url = o.url;
22015            this.ttl = o.ttl;
22016            this.cache = o.cache;
22017            this.prepare = o.prepare;
22018            this.transform = o.transform;
22019            this.transport = o.transport;
22020            this.thumbprint = o.thumbprint;
22021            this.storage = new PersistentStorage(o.cacheKey);
22022        }
22023        _.mixin(Prefetch.prototype, {
22024            _settings: function settings() {
22025                return {
22026                    url: this.url,
22027                    type: "GET",
22028                    dataType: "json"
22029                };
22030            },
22031            store: function store(data) {
22032                if (!this.cache) {
22033                    return;
22034                }
22035                this.storage.set(keys.data, data, this.ttl);
22036                this.storage.set(keys.protocol, location.protocol, this.ttl);
22037                this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
22038            },
22039            fromCache: function fromCache() {
22040                var stored = {}, isExpired;
22041                if (!this.cache) {
22042                    return null;
22043                }
22044                stored.data = this.storage.get(keys.data);
22045                stored.protocol = this.storage.get(keys.protocol);
22046                stored.thumbprint = this.storage.get(keys.thumbprint);
22047                isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
22048                return stored.data && !isExpired ? stored.data : null;
22049            },
22050            fromNetwork: function(cb) {
22051                var that = this, settings;
22052                if (!cb) {
22053                    return;
22054                }
22055                settings = this.prepare(this._settings());
22056                this.transport(settings).fail(onError).done(onResponse);
22057                function onError() {
22058                    cb(true);
22059                }
22060                function onResponse(resp) {
22061                    cb(null, that.transform(resp));
22062                }
22063            },
22064            clear: function clear() {
22065                this.storage.clear();
22066                return this;
22067            }
22068        });
22069        return Prefetch;
22070    }();
22071    var Remote = function() {
22072        "use strict";
22073        function Remote(o) {
22074            this.url = o.url;
22075            this.prepare = o.prepare;
22076            this.transform = o.transform;
22077            this.transport = new Transport({
22078                cache: o.cache,
22079                limiter: o.limiter,
22080                transport: o.transport
22081            });
22082        }
22083        _.mixin(Remote.prototype, {
22084            _settings: function settings() {
22085                return {
22086                    url: this.url,
22087                    type: "GET",
22088                    dataType: "json"
22089                };
22090            },
22091            get: function get(query, cb) {
22092                var that = this, settings;
22093                if (!cb) {
22094                    return;
22095                }
22096                query = query || "";
22097                settings = this.prepare(query, this._settings());
22098                return this.transport.get(settings, onResponse);
22099                function onResponse(err, resp) {
22100                    err ? cb([]) : cb(that.transform(resp));
22101                }
22102            },
22103            cancelLastRequest: function cancelLastRequest() {
22104                this.transport.cancel();
22105            }
22106        });
22107        return Remote;
22108    }();
22109    var oParser = function() {
22110        "use strict";
22111        return function parse(o) {
22112            var defaults, sorter;
22113            defaults = {
22114                initialize: true,
22115                identify: _.stringify,
22116                datumTokenizer: null,
22117                queryTokenizer: null,
22118                sufficient: 5,
22119                sorter: null,
22120                local: [],
22121                prefetch: null,
22122                remote: null
22123            };
22124            o = _.mixin(defaults, o || {});
22125            !o.datumTokenizer && $.error("datumTokenizer is required");
22126            !o.queryTokenizer && $.error("queryTokenizer is required");
22127            sorter = o.sorter;
22128            o.sorter = sorter ? function(x) {
22129                return x.sort(sorter);
22130            } : _.identity;
22131            o.local = _.isFunction(o.local) ? o.local() : o.local;
22132            o.prefetch = parsePrefetch(o.prefetch);
22133            o.remote = parseRemote(o.remote);
22134            return o;
22135        };
22136        function parsePrefetch(o) {
22137            var defaults;
22138            if (!o) {
22139                return null;
22140            }
22141            defaults = {
22142                url: null,
22143                ttl: 24 * 60 * 60 * 1e3,
22144                cache: true,
22145                cacheKey: null,
22146                thumbprint: "",
22147                prepare: _.identity,
22148                transform: _.identity,
22149                transport: null
22150            };
22151            o = _.isString(o) ? {
22152                url: o
22153            } : o;
22154            o = _.mixin(defaults, o);
22155            !o.url && $.error("prefetch requires url to be set");
22156            o.transform = o.filter || o.transform;
22157            o.cacheKey = o.cacheKey || o.url;
22158            o.thumbprint = VERSION + o.thumbprint;
22159            o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
22160            return o;
22161        }
22162        function parseRemote(o) {
22163            var defaults;
22164            if (!o) {
22165                return;
22166            }
22167            defaults = {
22168                url: null,
22169                cache: true,
22170                prepare: null,
22171                replace: null,
22172                wildcard: null,
22173                limiter: null,
22174                rateLimitBy: "debounce",
22175                rateLimitWait: 300,
22176                transform: _.identity,
22177                transport: null
22178            };
22179            o = _.isString(o) ? {
22180                url: o
22181            } : o;
22182            o = _.mixin(defaults, o);
22183            !o.url && $.error("remote requires url to be set");
22184            o.transform = o.filter || o.transform;
22185            o.prepare = toRemotePrepare(o);
22186            o.limiter = toLimiter(o);
22187            o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
22188            delete o.replace;
22189            delete o.wildcard;
22190            delete o.rateLimitBy;
22191            delete o.rateLimitWait;
22192            return o;
22193        }
22194        function toRemotePrepare(o) {
22195            var prepare, replace, wildcard;
22196            prepare = o.prepare;
22197            replace = o.replace;
22198            wildcard = o.wildcard;
22199            if (prepare) {
22200                return prepare;
22201            }
22202            if (replace) {
22203                prepare = prepareByReplace;
22204            } else if (o.wildcard) {
22205                prepare = prepareByWildcard;
22206            } else {
22207                prepare = idenityPrepare;
22208            }
22209            return prepare;
22210            function prepareByReplace(query, settings) {
22211                settings.url = replace(settings.url, query);
22212                return settings;
22213            }
22214            function prepareByWildcard(query, settings) {
22215                settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
22216                return settings;
22217            }
22218            function idenityPrepare(query, settings) {
22219                return settings;
22220            }
22221        }
22222        function toLimiter(o) {
22223            var limiter, method, wait;
22224            limiter = o.limiter;
22225            method = o.rateLimitBy;
22226            wait = o.rateLimitWait;
22227            if (!limiter) {
22228                limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
22229            }
22230            return limiter;
22231            function debounce(wait) {
22232                return function debounce(fn) {
22233                    return _.debounce(fn, wait);
22234                };
22235            }
22236            function throttle(wait) {
22237                return function throttle(fn) {
22238                    return _.throttle(fn, wait);
22239                };
22240            }
22241        }
22242        function callbackToDeferred(fn) {
22243            return function wrapper(o) {
22244                var deferred = $.Deferred();
22245                fn(o, onSuccess, onError);
22246                return deferred;
22247                function onSuccess(resp) {
22248                    _.defer(function() {
22249                        deferred.resolve(resp);
22250                    });
22251                }
22252                function onError(err) {
22253                    _.defer(function() {
22254                        deferred.reject(err);
22255                    });
22256                }
22257            };
22258        }
22259    }();
22260    var Bloodhound = function() {
22261        "use strict";
22262        var old;
22263        old = window && window.Bloodhound;
22264        function Bloodhound(o) {
22265            o = oParser(o);
22266            this.sorter = o.sorter;
22267            this.identify = o.identify;
22268            this.sufficient = o.sufficient;
22269            this.local = o.local;
22270            this.remote = o.remote ? new Remote(o.remote) : null;
22271            this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
22272            this.index = new SearchIndex({
22273                identify: this.identify,
22274                datumTokenizer: o.datumTokenizer,
22275                queryTokenizer: o.queryTokenizer
22276            });
22277            o.initialize !== false && this.initialize();
22278        }
22279        Bloodhound.noConflict = function noConflict() {
22280            window && (window.Bloodhound = old);
22281            return Bloodhound;
22282        };
22283        Bloodhound.tokenizers = tokenizers;
22284        _.mixin(Bloodhound.prototype, {
22285            __ttAdapter: function ttAdapter() {
22286                var that = this;
22287                return this.remote ? withAsync : withoutAsync;
22288                function withAsync(query, sync, async) {
22289                    return that.search(query, sync, async);
22290                }
22291                function withoutAsync(query, sync) {
22292                    return that.search(query, sync);
22293                }
22294            },
22295            _loadPrefetch: function loadPrefetch() {
22296                var that = this, deferred, serialized;
22297                deferred = $.Deferred();
22298                if (!this.prefetch) {
22299                    deferred.resolve();
22300                } else if (serialized = this.prefetch.fromCache()) {
22301                    this.index.bootstrap(serialized);
22302                    deferred.resolve();
22303                } else {
22304                    this.prefetch.fromNetwork(done);
22305                }
22306                return deferred.promise();
22307                function done(err, data) {
22308                    if (err) {
22309                        return deferred.reject();
22310                    }
22311                    that.add(data);
22312                    that.prefetch.store(that.index.serialize());
22313                    deferred.resolve();
22314                }
22315            },
22316            _initialize: function initialize() {
22317                var that = this, deferred;
22318                this.clear();
22319                (this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
22320                return this.initPromise;
22321                function addLocalToIndex() {
22322                    that.add(that.local);
22323                }
22324            },
22325            initialize: function initialize(force) {
22326                return !this.initPromise || force ? this._initialize() : this.initPromise;
22327            },
22328            add: function add(data) {
22329                this.index.add(data);
22330                return this;
22331            },
22332            get: function get(ids) {
22333                ids = _.isArray(ids) ? ids : [].slice.call(arguments);
22334                return this.index.get(ids);
22335            },
22336            search: function search(query, sync, async) {
22337                var that = this, local;
22338                local = this.sorter(this.index.search(query));
22339                sync(this.remote ? local.slice() : local);
22340                if (this.remote && local.length < this.sufficient) {
22341                    this.remote.get(query, processRemote);
22342                } else if (this.remote) {
22343                    this.remote.cancelLastRequest();
22344                }
22345                return this;
22346                function processRemote(remote) {
vendor: 3,453 bytes, lines 22347-22446
22347                    var nonDuplicates = [];
22348                    _.each(remote, function(r) {
22349                        !_.some(local, function(l) {
22350                            return that.identify(r) === that.identify(l);
22351                        }) && nonDuplicates.push(r);
22352                    });
22353                    async && async(nonDuplicates);
22354                }
22355            },
22356            all: function all() {
22357                return this.index.all();
22358            },
22359            clear: function clear() {
22360                this.index.reset();
22361                return this;
22362            },
22363            clearPrefetchCache: function clearPrefetchCache() {
22364                this.prefetch && this.prefetch.clear();
22365                return this;
22366            },
22367            clearRemoteCache: function clearRemoteCache() {
22368                Transport.resetCache();
22369                return this;
22370            },
22371            ttAdapter: function ttAdapter() {
22372                return this.__ttAdapter();
22373            }
22374        });
22375        return Bloodhound;
22376    }();
22377    return Bloodhound;
22378});
22379
22380(function(root, factory) {
22381    if (typeof define === "function" && define.amd) {
22382        define("typeahead.js", [ "jquery" ], function(a0) {
22383            return factory(a0);
22384        });
22385    } else if (typeof exports === "object") {
22386        module.exports = factory(require("jquery"));
22387    } else {
22388        factory(jQuery);
22389    }
22390})(this, function($) {
22391    var _ = function() {
22392        "use strict";
22393        return {
22394            isMsie: function() {
22395                return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
22396            },
22397            isBlankString: function(str) {
22398                return !str || /^\s*$/.test(str);
22399            },
22400            escapeRegExChars: function(str) {
22401                return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
22402            },
22403            isString: function(obj) {
22404                return typeof obj === "string";
22405            },
22406            isNumber: function(obj) {
22407                return typeof obj === "number";
22408            },
22409            isArray: $.isArray,
22410            isFunction: $.isFunction,
22411            isObject: $.isPlainObject,
22412            isUndefined: function(obj) {
22413                return typeof obj === "undefined";
22414            },
22415            isElement: function(obj) {
22416                return !!(obj && obj.nodeType === 1);
22417            },
22418            isJQuery: function(obj) {
22419                return obj instanceof $;
22420            },
22421            toStr: function toStr(s) {
22422                return _.isUndefined(s) || s === null ? "" : s + "";
22423            },
22424            bind: $.proxy,
22425            each: function(collection, cb) {
22426                $.each(collection, reverseArgs);
22427                function reverseArgs(index, value) {
22428                    return cb(value, index);
22429                }
22430            },
22431            map: $.map,
22432            filter: $.grep,
22433            every: function(obj, test) {
22434                var result = true;
22435                if (!obj) {
22436                    return result;
22437                }
22438                $.each(obj, function(key, val) {
22439                    if (!(result = test.call(null, val, key, obj))) {
22440                        return false;
22441                    }
22442                });
22443                return !!result;
22444            },
22445            some: function(obj, test) {
22446                var result = false;
vendor: 60,610 bytes, lines 22447-23911
22447                if (!obj) {
22448                    return result;
22449                }
22450                $.each(obj, function(key, val) {
22451                    if (result = test.call(null, val, key, obj)) {
22452                        return false;
22453                    }
22454                });
22455                return !!result;
22456            },
22457            mixin: $.extend,
22458            identity: function(x) {
22459                return x;
22460            },
22461            clone: function(obj) {
22462                return $.extend(true, {}, obj);
22463            },
22464            getIdGenerator: function() {
22465                var counter = 0;
22466                return function() {
22467                    return counter++;
22468                };
22469            },
22470            templatify: function templatify(obj) {
22471                return $.isFunction(obj) ? obj : template;
22472                function template() {
22473                    return String(obj);
22474                }
22475            },
22476            defer: function(fn) {
22477                setTimeout(fn, 0);
22478            },
22479            debounce: function(func, wait, immediate) {
22480                var timeout, result;
22481                return function() {
22482                    var context = this, args = arguments, later, callNow;
22483                    later = function() {
22484                        timeout = null;
22485                        if (!immediate) {
22486                            result = func.apply(context, args);
22487                        }
22488                    };
22489                    callNow = immediate && !timeout;
22490                    clearTimeout(timeout);
22491                    timeout = setTimeout(later, wait);
22492                    if (callNow) {
22493                        result = func.apply(context, args);
22494                    }
22495                    return result;
22496                };
22497            },
22498            throttle: function(func, wait) {
22499                var context, args, timeout, result, previous, later;
22500                previous = 0;
22501                later = function() {
22502                    previous = new Date();
22503                    timeout = null;
22504                    result = func.apply(context, args);
22505                };
22506                return function() {
22507                    var now = new Date(), remaining = wait - (now - previous);
22508                    context = this;
22509                    args = arguments;
22510                    if (remaining <= 0) {
22511                        clearTimeout(timeout);
22512                        timeout = null;
22513                        previous = now;
22514                        result = func.apply(context, args);
22515                    } else if (!timeout) {
22516                        timeout = setTimeout(later, remaining);
22517                    }
22518                    return result;
22519                };
22520            },
22521            stringify: function(val) {
22522                return _.isString(val) ? val : JSON.stringify(val);
22523            },
22524            noop: function() {}
22525        };
22526    }();
22527    var WWW = function() {
22528        "use strict";
22529        var defaultClassNames = {
22530            wrapper: "twitter-typeahead",
22531            input: "tt-input",
22532            hint: "tt-hint",
22533            menu: "tt-menu",
22534            dataset: "tt-dataset",
22535            suggestion: "tt-suggestion",
22536            selectable: "tt-selectable",
22537            empty: "tt-empty",
22538            open: "tt-open",
22539            cursor: "tt-cursor",
22540            highlight: "tt-highlight"
22541        };
22542        return build;
22543        function build(o) {
22544            var www, classes;
22545            classes = _.mixin({}, defaultClassNames, o);
22546            www = {
22547                css: buildCss(),
22548                classes: classes,
22549                html: buildHtml(classes),
22550                selectors: buildSelectors(classes)
22551            };
22552            return {
22553                css: www.css,
22554                html: www.html,
22555                classes: www.classes,
22556                selectors: www.selectors,
22557                mixin: function(o) {
22558                    _.mixin(o, www);
22559                }
22560            };
22561        }
22562        function buildHtml(c) {
22563            return {
22564                wrapper: '<span class="' + c.wrapper + '"></span>',
22565                menu: '<div class="' + c.menu + '"></div>'
22566            };
22567        }
22568        function buildSelectors(classes) {
22569            var selectors = {};
22570            _.each(classes, function(v, k) {
22571                selectors[k] = "." + v;
22572            });
22573            return selectors;
22574        }
22575        function buildCss() {
22576            var css = {
22577                wrapper: {
22578                    position: "relative",
22579                    display: "inline-block"
22580                },
22581                hint: {
22582                    position: "absolute",
22583                    top: "0",
22584                    left: "0",
22585                    borderColor: "transparent",
22586                    boxShadow: "none",
22587                    opacity: "1"
22588                },
22589                input: {
22590                    position: "relative",
22591                    verticalAlign: "top",
22592                    backgroundColor: "transparent"
22593                },
22594                inputWithNoHint: {
22595                    position: "relative",
22596                    verticalAlign: "top"
22597                },
22598                menu: {
22599                    position: "absolute",
22600                    top: "100%",
22601                    left: "0",
22602                    zIndex: "100",
22603                    display: "none"
22604                },
22605                ltr: {
22606                    left: "0",
22607                    right: "auto"
22608                },
22609                rtl: {
22610                    left: "auto",
22611                    right: " 0"
22612                }
22613            };
22614            if (_.isMsie()) {
22615                _.mixin(css.input, {
22616                    backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
22617                });
22618            }
22619            return css;
22620        }
22621    }();
22622    var EventBus = function() {
22623        "use strict";
22624        var namespace, deprecationMap;
22625        namespace = "typeahead:";
22626        deprecationMap = {
22627            render: "rendered",
22628            cursorchange: "cursorchanged",
22629            select: "selected",
22630            autocomplete: "autocompleted"
22631        };
22632        function EventBus(o) {
22633            if (!o || !o.el) {
22634                $.error("EventBus initialized without el");
22635            }
22636            this.$el = $(o.el);
22637        }
22638        _.mixin(EventBus.prototype, {
22639            _trigger: function(type, args) {
22640                var $e;
22641                $e = $.Event(namespace + type);
22642                (args = args || []).unshift($e);
22643                this.$el.trigger.apply(this.$el, args);
22644                return $e;
22645            },
22646            before: function(type) {
22647                var args, $e;
22648                args = [].slice.call(arguments, 1);
22649                $e = this._trigger("before" + type, args);
22650                return $e.isDefaultPrevented();
22651            },
22652            trigger: function(type) {
22653                var deprecatedType;
22654                this._trigger(type, [].slice.call(arguments, 1));
22655                if (deprecatedType = deprecationMap[type]) {
22656                    this._trigger(deprecatedType, [].slice.call(arguments, 1));
22657                }
22658            }
22659        });
22660        return EventBus;
22661    }();
22662    var EventEmitter = function() {
22663        "use strict";
22664        var splitter = /\s+/, nextTick = getNextTick();
22665        return {
22666            onSync: onSync,
22667            onAsync: onAsync,
22668            off: off,
22669            trigger: trigger
22670        };
22671        function on(method, types, cb, context) {
22672            var type;
22673            if (!cb) {
22674                return this;
22675            }
22676            types = types.split(splitter);
22677            cb = context ? bindContext(cb, context) : cb;
22678            this._callbacks = this._callbacks || {};
22679            while (type = types.shift()) {
22680                this._callbacks[type] = this._callbacks[type] || {
22681                    sync: [],
22682                    async: []
22683                };
22684                this._callbacks[type][method].push(cb);
22685            }
22686            return this;
22687        }
22688        function onAsync(types, cb, context) {
22689            return on.call(this, "async", types, cb, context);
22690        }
22691        function onSync(types, cb, context) {
22692            return on.call(this, "sync", types, cb, context);
22693        }
22694        function off(types) {
22695            var type;
22696            if (!this._callbacks) {
22697                return this;
22698            }
22699            types = types.split(splitter);
22700            while (type = types.shift()) {
22701                delete this._callbacks[type];
22702            }
22703            return this;
22704        }
22705        function trigger(types) {
22706            var type, callbacks, args, syncFlush, asyncFlush;
22707            if (!this._callbacks) {
22708                return this;
22709            }
22710            types = types.split(splitter);
22711            args = [].slice.call(arguments, 1);
22712            while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
22713                syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
22714                asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
22715                syncFlush() && nextTick(asyncFlush);
22716            }
22717            return this;
22718        }
22719        function getFlush(callbacks, context, args) {
22720            return flush;
22721            function flush() {
22722                var cancelled;
22723                for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
22724                    cancelled = callbacks[i].apply(context, args) === false;
22725                }
22726                return !cancelled;
22727            }
22728        }
22729        function getNextTick() {
22730            var nextTickFn;
22731            if (window.setImmediate) {
22732                nextTickFn = function nextTickSetImmediate(fn) {
22733                    setImmediate(function() {
22734                        fn();
22735                    });
22736                };
22737            } else {
22738                nextTickFn = function nextTickSetTimeout(fn) {
22739                    setTimeout(function() {
22740                        fn();
22741                    }, 0);
22742                };
22743            }
22744            return nextTickFn;
22745        }
22746        function bindContext(fn, context) {
22747            return fn.bind ? fn.bind(context) : function() {
22748                fn.apply(context, [].slice.call(arguments, 0));
22749            };
22750        }
22751    }();
22752    var highlight = function(doc) {
22753        "use strict";
22754        var defaults = {
22755            node: null,
22756            pattern: null,
22757            tagName: "strong",
22758            className: null,
22759            wordsOnly: false,
22760            caseSensitive: false
22761        };
22762        return function hightlight(o) {
22763            var regex;
22764            o = _.mixin({}, defaults, o);
22765            if (!o.node || !o.pattern) {
22766                return;
22767            }
22768            o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
22769            regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
22770            traverse(o.node, hightlightTextNode);
22771            function hightlightTextNode(textNode) {
22772                var match, patternNode, wrapperNode;
22773                if (match = regex.exec(textNode.data)) {
22774                    wrapperNode = doc.createElement(o.tagName);
22775                    o.className && (wrapperNode.className = o.className);
22776                    patternNode = textNode.splitText(match.index);
22777                    patternNode.splitText(match[0].length);
22778                    wrapperNode.appendChild(patternNode.cloneNode(true));
22779                    textNode.parentNode.replaceChild(wrapperNode, patternNode);
22780                }
22781                return !!match;
22782            }
22783            function traverse(el, hightlightTextNode) {
22784                var childNode, TEXT_NODE_TYPE = 3;
22785                for (var i = 0; i < el.childNodes.length; i++) {
22786                    childNode = el.childNodes[i];
22787                    if (childNode.nodeType === TEXT_NODE_TYPE) {
22788                        i += hightlightTextNode(childNode) ? 1 : 0;
22789                    } else {
22790                        traverse(childNode, hightlightTextNode);
22791                    }
22792                }
22793            }
22794        };
22795        function getRegex(patterns, caseSensitive, wordsOnly) {
22796            var escapedPatterns = [], regexStr;
22797            for (var i = 0, len = patterns.length; i < len; i++) {
22798                escapedPatterns.push(_.escapeRegExChars(patterns[i]));
22799            }
22800            regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
22801            return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
22802        }
22803    }(window.document);
22804    var Input = function() {
22805        "use strict";
22806        var specialKeyCodeMap;
22807        specialKeyCodeMap = {
22808            9: "tab",
22809            27: "esc",
22810            37: "left",
22811            39: "right",
22812            13: "enter",
22813            38: "up",
22814            40: "down"
22815        };
22816        function Input(o, www) {
22817            o = o || {};
22818            if (!o.input) {
22819                $.error("input is missing");
22820            }
22821            www.mixin(this);
22822            this.$hint = $(o.hint);
22823            this.$input = $(o.input);
22824            this.query = this.$input.val();
22825            this.queryWhenFocused = this.hasFocus() ? this.query : null;
22826            this.$overflowHelper = buildOverflowHelper(this.$input);
22827            this._checkLanguageDirection();
22828            if (this.$hint.length === 0) {
22829                this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
22830            }
22831        }
22832        Input.normalizeQuery = function(str) {
22833            return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
22834        };
22835        _.mixin(Input.prototype, EventEmitter, {
22836            _onBlur: function onBlur() {
22837                this.resetInputValue();
22838                this.trigger("blurred");
22839            },
22840            _onFocus: function onFocus() {
22841                this.queryWhenFocused = this.query;
22842                this.trigger("focused");
22843            },
22844            _onKeydown: function onKeydown($e) {
22845                var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
22846                this._managePreventDefault(keyName, $e);
22847                if (keyName && this._shouldTrigger(keyName, $e)) {
22848                    this.trigger(keyName + "Keyed", $e);
22849                }
22850            },
22851            _onInput: function onInput() {
22852                this._setQuery(this.getInputValue());
22853                this.clearHintIfInvalid();
22854                this._checkLanguageDirection();
22855            },
22856            _managePreventDefault: function managePreventDefault(keyName, $e) {
22857                var preventDefault;
22858                switch (keyName) {
22859                  case "up":
22860                  case "down":
22861                    preventDefault = !withModifier($e);
22862                    break;
22863
22864                  default:
22865                    preventDefault = false;
22866                }
22867                preventDefault && $e.preventDefault();
22868            },
22869            _shouldTrigger: function shouldTrigger(keyName, $e) {
22870                var trigger;
22871                switch (keyName) {
22872                  case "tab":
22873                    trigger = !withModifier($e);
22874                    break;
22875
22876                  default:
22877                    trigger = true;
22878                }
22879                return trigger;
22880            },
22881            _checkLanguageDirection: function checkLanguageDirection() {
22882                var dir = (this.$input.css("direction") || "ltr").toLowerCase();
22883                if (this.dir !== dir) {
22884                    this.dir = dir;
22885                    this.$hint.attr("dir", dir);
22886                    this.trigger("langDirChanged", dir);
22887                }
22888            },
22889            _setQuery: function setQuery(val, silent) {
22890                var areEquivalent, hasDifferentWhitespace;
22891                areEquivalent = areQueriesEquivalent(val, this.query);
22892                hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
22893                this.query = val;
22894                if (!silent && !areEquivalent) {
22895                    this.trigger("queryChanged", this.query);
22896                } else if (!silent && hasDifferentWhitespace) {
22897                    this.trigger("whitespaceChanged", this.query);
22898                }
22899            },
22900            bind: function() {
22901                var that = this, onBlur, onFocus, onKeydown, onInput;
22902                onBlur = _.bind(this._onBlur, this);
22903                onFocus = _.bind(this._onFocus, this);
22904                onKeydown = _.bind(this._onKeydown, this);
22905                onInput = _.bind(this._onInput, this);
22906                this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
22907                if (!_.isMsie() || _.isMsie() > 9) {
22908                    this.$input.on("input.tt", onInput);
22909                } else {
22910                    this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
22911                        if (specialKeyCodeMap[$e.which || $e.keyCode]) {
22912                            return;
22913                        }
22914                        _.defer(_.bind(that._onInput, that, $e));
22915                    });
22916                }
22917                return this;
22918            },
22919            focus: function focus() {
22920                this.$input.focus();
22921            },
22922            blur: function blur() {
22923                this.$input.blur();
22924            },
22925            getLangDir: function getLangDir() {
22926                return this.dir;
22927            },
22928            getQuery: function getQuery() {
22929                return this.query || "";
22930            },
22931            setQuery: function setQuery(val, silent) {
22932                this.setInputValue(val);
22933                this._setQuery(val, silent);
22934            },
22935            hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
22936                return this.query !== this.queryWhenFocused;
22937            },
22938            getInputValue: function getInputValue() {
22939                return this.$input.val();
22940            },
22941            setInputValue: function setInputValue(value) {
22942                this.$input.val(value);
22943                this.clearHintIfInvalid();
22944                this._checkLanguageDirection();
22945            },
22946            resetInputValue: function resetInputValue() {
22947                this.setInputValue(this.query);
22948            },
22949            getHint: function getHint() {
22950                return this.$hint.val();
22951            },
22952            setHint: function setHint(value) {
22953                this.$hint.val(value);
22954            },
22955            clearHint: function clearHint() {
22956                this.setHint("");
22957            },
22958            clearHintIfInvalid: function clearHintIfInvalid() {
22959                var val, hint, valIsPrefixOfHint, isValid;
22960                val = this.getInputValue();
22961                hint = this.getHint();
22962                valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
22963                isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
22964                !isValid && this.clearHint();
22965            },
22966            hasFocus: function hasFocus() {
22967                return this.$input.is(":focus");
22968            },
22969            hasOverflow: function hasOverflow() {
22970                var constraint = this.$input.width() - 2;
22971                this.$overflowHelper.text(this.getInputValue());
22972                return this.$overflowHelper.width() >= constraint;
22973            },
22974            isCursorAtEnd: function() {
22975                var valueLength, selectionStart, range;
22976                valueLength = this.$input.val().length;
22977                selectionStart = this.$input[0].selectionStart;
22978                if (_.isNumber(selectionStart)) {
22979                    return selectionStart === valueLength;
22980                } else if (document.selection) {
22981                    range = document.selection.createRange();
22982                    range.moveStart("character", -valueLength);
22983                    return valueLength === range.text.length;
22984                }
22985                return true;
22986            },
22987            destroy: function destroy() {
22988                this.$hint.off(".tt");
22989                this.$input.off(".tt");
22990                this.$overflowHelper.remove();
22991                this.$hint = this.$input = this.$overflowHelper = $("<div>");
22992            }
22993        });
22994        return Input;
22995        function buildOverflowHelper($input) {
22996            return $('<pre aria-hidden="true"></pre>').css({
22997                position: "absolute",
22998                visibility: "hidden",
22999                whiteSpace: "pre",
23000                fontFamily: $input.css("font-family"),
23001                fontSize: $input.css("font-size"),
23002                fontStyle: $input.css("font-style"),
23003                fontVariant: $input.css("font-variant"),
23004                fontWeight: $input.css("font-weight"),
23005                wordSpacing: $input.css("word-spacing"),
23006                letterSpacing: $input.css("letter-spacing"),
23007                textIndent: $input.css("text-indent"),
23008                textRendering: $input.css("text-rendering"),
23009                textTransform: $input.css("text-transform")
23010            }).insertAfter($input);
23011        }
23012        function areQueriesEquivalent(a, b) {
23013            return Input.normalizeQuery(a) === Input.normalizeQuery(b);
23014        }
23015        function withModifier($e) {
23016            return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
23017        }
23018    }();
23019    var Dataset = function() {
23020        "use strict";
23021        var keys, nameGenerator;
23022        keys = {
23023            val: "tt-selectable-display",
23024            obj: "tt-selectable-object"
23025        };
23026        nameGenerator = _.getIdGenerator();
23027        function Dataset(o, www) {
23028            o = o || {};
23029            o.templates = o.templates || {};
23030            o.templates.notFound = o.templates.notFound || o.templates.empty;
23031            if (!o.source) {
23032                $.error("missing source");
23033            }
23034            if (!o.node) {
23035                $.error("missing node");
23036            }
23037            if (o.name && !isValidName(o.name)) {
23038                $.error("invalid dataset name: " + o.name);
23039            }
23040            www.mixin(this);
23041            this.highlight = !!o.highlight;
23042            this.name = o.name || nameGenerator();
23043            this.limit = o.limit || 5;
23044            this.displayFn = getDisplayFn(o.display || o.displayKey);
23045            this.templates = getTemplates(o.templates, this.displayFn);
23046            this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
23047            this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
23048            this._resetLastSuggestion();
23049            this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
23050        }
23051        Dataset.extractData = function extractData(el) {
23052            var $el = $(el);
23053            if ($el.data(keys.obj)) {
23054                return {
23055                    val: $el.data(keys.val) || "",
23056                    obj: $el.data(keys.obj) || null
23057                };
23058            }
23059            return null;
23060        };
23061        _.mixin(Dataset.prototype, EventEmitter, {
23062            _overwrite: function overwrite(query, suggestions) {
23063                suggestions = suggestions || [];
23064                if (suggestions.length) {
23065                    this._renderSuggestions(query, suggestions);
23066                } else if (this.async && this.templates.pending) {
23067                    this._renderPending(query);
23068                } else if (!this.async && this.templates.notFound) {
23069                    this._renderNotFound(query);
23070                } else {
23071                    this._empty();
23072                }
23073                this.trigger("rendered", this.name, suggestions, false);
23074            },
23075            _append: function append(query, suggestions) {
23076                suggestions = suggestions || [];
23077                if (suggestions.length && this.$lastSuggestion.length) {
23078                    this._appendSuggestions(query, suggestions);
23079                } else if (suggestions.length) {
23080                    this._renderSuggestions(query, suggestions);
23081                } else if (!this.$lastSuggestion.length && this.templates.notFound) {
23082                    this._renderNotFound(query);
23083                }
23084                this.trigger("rendered", this.name, suggestions, true);
23085            },
23086            _renderSuggestions: function renderSuggestions(query, suggestions) {
23087                var $fragment;
23088                $fragment = this._getSuggestionsFragment(query, suggestions);
23089                this.$lastSuggestion = $fragment.children().last();
23090                this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
23091            },
23092            _appendSuggestions: function appendSuggestions(query, suggestions) {
23093                var $fragment, $lastSuggestion;
23094                $fragment = this._getSuggestionsFragment(query, suggestions);
23095                $lastSuggestion = $fragment.children().last();
23096                this.$lastSuggestion.after($fragment);
23097                this.$lastSuggestion = $lastSuggestion;
23098            },
23099            _renderPending: function renderPending(query) {
23100                var template = this.templates.pending;
23101                this._resetLastSuggestion();
23102                template && this.$el.html(template({
23103                    query: query,
23104                    dataset: this.name
23105                }));
23106            },
23107            _renderNotFound: function renderNotFound(query) {
23108                var template = this.templates.notFound;
23109                this._resetLastSuggestion();
23110                template && this.$el.html(template({
23111                    query: query,
23112                    dataset: this.name
23113                }));
23114            },
23115            _empty: function empty() {
23116                this.$el.empty();
23117                this._resetLastSuggestion();
23118            },
23119            _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
23120                var that = this, fragment;
23121                fragment = document.createDocumentFragment();
23122                _.each(suggestions, function getSuggestionNode(suggestion) {
23123                    var $el, context;
23124                    context = that._injectQuery(query, suggestion);
23125                    $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
23126                    fragment.appendChild($el[0]);
23127                });
23128                this.highlight && highlight({
23129                    className: this.classes.highlight,
23130                    node: fragment,
23131                    pattern: query
23132                });
23133                return $(fragment);
23134            },
23135            _getFooter: function getFooter(query, suggestions) {
23136                return this.templates.footer ? this.templates.footer({
23137                    query: query,
23138                    suggestions: suggestions,
23139                    dataset: this.name
23140                }) : null;
23141            },
23142            _getHeader: function getHeader(query, suggestions) {
23143                return this.templates.header ? this.templates.header({
23144                    query: query,
23145                    suggestions: suggestions,
23146                    dataset: this.name
23147                }) : null;
23148            },
23149            _resetLastSuggestion: function resetLastSuggestion() {
23150                this.$lastSuggestion = $();
23151            },
23152            _injectQuery: function injectQuery(query, obj) {
23153                return _.isObject(obj) ? _.mixin({
23154                    _query: query
23155                }, obj) : obj;
23156            },
23157            update: function update(query) {
23158                var that = this, canceled = false, syncCalled = false, rendered = 0;
23159                this.cancel();
23160                this.cancel = function cancel() {
23161                    canceled = true;
23162                    that.cancel = $.noop;
23163                    that.async && that.trigger("asyncCanceled", query);
23164                };
23165                this.source(query, sync, async);
23166                !syncCalled && sync([]);
23167                function sync(suggestions) {
23168                    if (syncCalled) {
23169                        return;
23170                    }
23171                    syncCalled = true;
23172                    suggestions = (suggestions || []).slice(0, that.limit);
23173                    rendered = suggestions.length;
23174                    that._overwrite(query, suggestions);
23175                    if (rendered < that.limit && that.async) {
23176                        that.trigger("asyncRequested", query);
23177                    }
23178                }
23179                function async(suggestions) {
23180                    suggestions = suggestions || [];
23181                    if (!canceled && rendered < that.limit) {
23182                        that.cancel = $.noop;
23183                        rendered += suggestions.length;
23184                        that._append(query, suggestions.slice(0, that.limit - rendered));
23185                        that.async && that.trigger("asyncReceived", query);
23186                    }
23187                }
23188            },
23189            cancel: $.noop,
23190            clear: function clear() {
23191                this._empty();
23192                this.cancel();
23193                this.trigger("cleared");
23194            },
23195            isEmpty: function isEmpty() {
23196                return this.$el.is(":empty");
23197            },
23198            destroy: function destroy() {
23199                this.$el = $("<div>");
23200            }
23201        });
23202        return Dataset;
23203        function getDisplayFn(display) {
23204            display = display || _.stringify;
23205            return _.isFunction(display) ? display : displayFn;
23206            function displayFn(obj) {
23207                return obj[display];
23208            }
23209        }
23210        function getTemplates(templates, displayFn) {
23211            return {
23212                notFound: templates.notFound && _.templatify(templates.notFound),
23213                pending: templates.pending && _.templatify(templates.pending),
23214                header: templates.header && _.templatify(templates.header),
23215                footer: templates.footer && _.templatify(templates.footer),
23216                suggestion: templates.suggestion || suggestionTemplate
23217            };
23218            function suggestionTemplate(context) {
23219                return $("<div>").text(displayFn(context));
23220            }
23221        }
23222        function isValidName(str) {
23223            return /^[_a-zA-Z0-9-]+$/.test(str);
23224        }
23225    }();
23226    var Menu = function() {
23227        "use strict";
23228        function Menu(o, www) {
23229            var that = this;
23230            o = o || {};
23231            if (!o.node) {
23232                $.error("node is required");
23233            }
23234            www.mixin(this);
23235            this.$node = $(o.node);
23236            this.query = null;
23237            this.datasets = _.map(o.datasets, initializeDataset);
23238            function initializeDataset(oDataset) {
23239                var node = that.$node.find(oDataset.node).first();
23240                oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
23241                return new Dataset(oDataset, www);
23242            }
23243        }
23244        _.mixin(Menu.prototype, EventEmitter, {
23245            _onSelectableClick: function onSelectableClick($e) {
23246                this.trigger("selectableClicked", $($e.currentTarget));
23247            },
23248            _onRendered: function onRendered(type, dataset, suggestions, async) {
23249                this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
23250                this.trigger("datasetRendered", dataset, suggestions, async);
23251            },
23252            _onCleared: function onCleared() {
23253                this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
23254                this.trigger("datasetCleared");
23255            },
23256            _propagate: function propagate() {
23257                this.trigger.apply(this, arguments);
23258            },
23259            _allDatasetsEmpty: function allDatasetsEmpty() {
23260                return _.every(this.datasets, isDatasetEmpty);
23261                function isDatasetEmpty(dataset) {
23262                    return dataset.isEmpty();
23263                }
23264            },
23265            _getSelectables: function getSelectables() {
23266                return this.$node.find(this.selectors.selectable);
23267            },
23268            _removeCursor: function _removeCursor() {
23269                var $selectable = this.getActiveSelectable();
23270                $selectable && $selectable.removeClass(this.classes.cursor);
23271            },
23272            _ensureVisible: function ensureVisible($el) {
23273                var elTop, elBottom, nodeScrollTop, nodeHeight;
23274                elTop = $el.position().top;
23275                elBottom = elTop + $el.outerHeight(true);
23276                nodeScrollTop = this.$node.scrollTop();
23277                nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
23278                if (elTop < 0) {
23279                    this.$node.scrollTop(nodeScrollTop + elTop);
23280                } else if (nodeHeight < elBottom) {
23281                    this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
23282                }
23283            },
23284            bind: function() {
23285                var that = this, onSelectableClick;
23286                onSelectableClick = _.bind(this._onSelectableClick, this);
23287                this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
23288                _.each(this.datasets, function(dataset) {
23289                    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);
23290                });
23291                return this;
23292            },
23293            isOpen: function isOpen() {
23294                return this.$node.hasClass(this.classes.open);
23295            },
23296            open: function open() {
23297                this.$node.addClass(this.classes.open);
23298            },
23299            close: function close() {
23300                this.$node.removeClass(this.classes.open);
23301                this._removeCursor();
23302            },
23303            setLanguageDirection: function setLanguageDirection(dir) {
23304                this.$node.attr("dir", dir);
23305            },
23306            selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
23307                var $selectables, $oldCursor, oldIndex, newIndex;
23308                $oldCursor = this.getActiveSelectable();
23309                $selectables = this._getSelectables();
23310                oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
23311                newIndex = oldIndex + delta;
23312                newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
23313                newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
23314                return newIndex === -1 ? null : $selectables.eq(newIndex);
23315            },
23316            setCursor: function setCursor($selectable) {
23317                this._removeCursor();
23318                if ($selectable = $selectable && $selectable.first()) {
23319                    $selectable.addClass(this.classes.cursor);
23320                    this._ensureVisible($selectable);
23321                }
23322            },
23323            getSelectableData: function getSelectableData($el) {
23324                return $el && $el.length ? Dataset.extractData($el) : null;
23325            },
23326            getActiveSelectable: function getActiveSelectable() {
23327                var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
23328                return $selectable.length ? $selectable : null;
23329            },
23330            getTopSelectable: function getTopSelectable() {
23331                var $selectable = this._getSelectables().first();
23332                return $selectable.length ? $selectable : null;
23333            },
23334            update: function update(query) {
23335                var isValidUpdate = query !== this.query;
23336                if (isValidUpdate) {
23337                    this.query = query;
23338                    _.each(this.datasets, updateDataset);
23339                }
23340                return isValidUpdate;
23341                function updateDataset(dataset) {
23342                    dataset.update(query);
23343                }
23344            },
23345            empty: function empty() {
23346                _.each(this.datasets, clearDataset);
23347                this.query = null;
23348                this.$node.addClass(this.classes.empty);
23349                function clearDataset(dataset) {
23350                    dataset.clear();
23351                }
23352            },
23353            destroy: function destroy() {
23354                this.$node.off(".tt");
23355                this.$node = $("<div>");
23356                _.each(this.datasets, destroyDataset);
23357                function destroyDataset(dataset) {
23358                    dataset.destroy();
23359                }
23360            }
23361        });
23362        return Menu;
23363    }();
23364    var DefaultMenu = function() {
23365        "use strict";
23366        var s = Menu.prototype;
23367        function DefaultMenu() {
23368            Menu.apply(this, [].slice.call(arguments, 0));
23369        }
23370        _.mixin(DefaultMenu.prototype, Menu.prototype, {
23371            open: function open() {
23372                !this._allDatasetsEmpty() && this._show();
23373                return s.open.apply(this, [].slice.call(arguments, 0));
23374            },
23375            close: function close() {
23376                this._hide();
23377                return s.close.apply(this, [].slice.call(arguments, 0));
23378            },
23379            _onRendered: function onRendered() {
23380                if (this._allDatasetsEmpty()) {
23381                    this._hide();
23382                } else {
23383                    this.isOpen() && this._show();
23384                }
23385                return s._onRendered.apply(this, [].slice.call(arguments, 0));
23386            },
23387            _onCleared: function onCleared() {
23388                if (this._allDatasetsEmpty()) {
23389                    this._hide();
23390                } else {
23391                    this.isOpen() && this._show();
23392                }
23393                return s._onCleared.apply(this, [].slice.call(arguments, 0));
23394            },
23395            setLanguageDirection: function setLanguageDirection(dir) {
23396                this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
23397                return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
23398            },
23399            _hide: function hide() {
23400                this.$node.hide();
23401            },
23402            _show: function show() {
23403                this.$node.css("display", "block");
23404            }
23405        });
23406        return DefaultMenu;
23407    }();
23408    var Typeahead = function() {
23409        "use strict";
23410        function Typeahead(o, www) {
23411            var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
23412            o = o || {};
23413            if (!o.input) {
23414                $.error("missing input");
23415            }
23416            if (!o.menu) {
23417                $.error("missing menu");
23418            }
23419            if (!o.eventBus) {
23420                $.error("missing event bus");
23421            }
23422            www.mixin(this);
23423            this.eventBus = o.eventBus;
23424            this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
23425            this.input = o.input;
23426            this.menu = o.menu;
23427            this.enabled = true;
23428            this.active = false;
23429            this.input.hasFocus() && this.activate();
23430            this.dir = this.input.getLangDir();
23431            this._hacks();
23432            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);
23433            onFocused = c(this, "activate", "open", "_onFocused");
23434            onBlurred = c(this, "deactivate", "_onBlurred");
23435            onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
23436            onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
23437            onEscKeyed = c(this, "isActive", "_onEscKeyed");
23438            onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
23439            onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
23440            onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
23441            onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
23442            onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
23443            onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
23444            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);
23445        }
23446        _.mixin(Typeahead.prototype, {
23447            _hacks: function hacks() {
23448                var $input, $menu;
23449                $input = this.input.$input || $("<div>");
23450                $menu = this.menu.$node || $("<div>");
23451                $input.on("blur.tt", function($e) {
23452                    var active, isActive, hasActive;
23453                    active = document.activeElement;
23454                    isActive = $menu.is(active);
23455                    hasActive = $menu.has(active).length > 0;
23456                    if (_.isMsie() && (isActive || hasActive)) {
23457                        $e.preventDefault();
23458                        $e.stopImmediatePropagation();
23459                        _.defer(function() {
23460                            $input.focus();
23461                        });
23462                    }
23463                });
23464                $menu.on("mousedown.tt", function($e) {
23465                    $e.preventDefault();
23466                });
23467            },
23468            _onSelectableClicked: function onSelectableClicked(type, $el) {
23469                this.select($el);
23470            },
23471            _onDatasetCleared: function onDatasetCleared() {
23472                this._updateHint();
23473            },
23474            _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
23475                this._updateHint();
23476                this.eventBus.trigger("render", suggestions, async, dataset);
23477            },
23478            _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
23479                this.eventBus.trigger("asyncrequest", query, dataset);
23480            },
23481            _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
23482                this.eventBus.trigger("asynccancel", query, dataset);
23483            },
23484            _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
23485                this.eventBus.trigger("asyncreceive", query, dataset);
23486            },
23487            _onFocused: function onFocused() {
23488                this._minLengthMet() && this.menu.update(this.input.getQuery());
23489            },
23490            _onBlurred: function onBlurred() {
23491                if (this.input.hasQueryChangedSinceLastFocus()) {
23492                    this.eventBus.trigger("change", this.input.getQuery());
23493                }
23494            },
23495            _onEnterKeyed: function onEnterKeyed(type, $e) {
23496                var $selectable;
23497                if ($selectable = this.menu.getActiveSelectable()) {
23498                    this.select($selectable) && $e.preventDefault();
23499                }
23500            },
23501            _onTabKeyed: function onTabKeyed(type, $e) {
23502                var $selectable;
23503                if ($selectable = this.menu.getActiveSelectable()) {
23504                    this.select($selectable) && $e.preventDefault();
23505                } else if ($selectable = this.menu.getTopSelectable()) {
23506                    this.autocomplete($selectable) && $e.preventDefault();
23507                }
23508            },
23509            _onEscKeyed: function onEscKeyed() {
23510                this.close();
23511            },
23512            _onUpKeyed: function onUpKeyed() {
23513                this.moveCursor(-1);
23514            },
23515            _onDownKeyed: function onDownKeyed() {
23516                this.moveCursor(+1);
23517            },
23518            _onLeftKeyed: function onLeftKeyed() {
23519                if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
23520                    this.autocomplete(this.menu.getTopSelectable());
23521                }
23522            },
23523            _onRightKeyed: function onRightKeyed() {
23524                if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
23525                    this.autocomplete(this.menu.getTopSelectable());
23526                }
23527            },
23528            _onQueryChanged: function onQueryChanged(e, query) {
23529                this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
23530            },
23531            _onWhitespaceChanged: function onWhitespaceChanged() {
23532                this._updateHint();
23533            },
23534            _onLangDirChanged: function onLangDirChanged(e, dir) {
23535                if (this.dir !== dir) {
23536                    this.dir = dir;
23537                    this.menu.setLanguageDirection(dir);
23538                }
23539            },
23540            _openIfActive: function openIfActive() {
23541                this.isActive() && this.open();
23542            },
23543            _minLengthMet: function minLengthMet(query) {
23544                query = _.isString(query) ? query : this.input.getQuery() || "";
23545                return query.length >= this.minLength;
23546            },
23547            _updateHint: function updateHint() {
23548                var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
23549                $selectable = this.menu.getTopSelectable();
23550                data = this.menu.getSelectableData($selectable);
23551                val = this.input.getInputValue();
23552                if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
23553                    query = Input.normalizeQuery(val);
23554                    escapedQuery = _.escapeRegExChars(query);
23555                    frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
23556                    match = frontMatchRegEx.exec(data.val);
23557                    match && this.input.setHint(val + match[1]);
23558                } else {
23559                    this.input.clearHint();
23560                }
23561            },
23562            isEnabled: function isEnabled() {
23563                return this.enabled;
23564            },
23565            enable: function enable() {
23566                this.enabled = true;
23567            },
23568            disable: function disable() {
23569                this.enabled = false;
23570            },
23571            isActive: function isActive() {
23572                return this.active;
23573            },
23574            activate: function activate() {
23575                if (this.isActive()) {
23576                    return true;
23577                } else if (!this.isEnabled() || this.eventBus.before("active")) {
23578                    return false;
23579                } else {
23580                    this.active = true;
23581                    this.eventBus.trigger("active");
23582                    return true;
23583                }
23584            },
23585            deactivate: function deactivate() {
23586                if (!this.isActive()) {
23587                    return true;
23588                } else if (this.eventBus.before("idle")) {
23589                    return false;
23590                } else {
23591                    this.active = false;
23592                    this.close();
23593                    this.eventBus.trigger("idle");
23594                    return true;
23595                }
23596            },
23597            isOpen: function isOpen() {
23598                return this.menu.isOpen();
23599            },
23600            open: function open() {
23601                if (!this.isOpen() && !this.eventBus.before("open")) {
23602                    this.menu.open();
23603                    this._updateHint();
23604                    this.eventBus.trigger("open");
23605                }
23606                return this.isOpen();
23607            },
23608            close: function close() {
23609                if (this.isOpen() && !this.eventBus.before("close")) {
23610                    this.menu.close();
23611                    this.input.clearHint();
23612                    this.input.resetInputValue();
23613                    this.eventBus.trigger("close");
23614                }
23615                return !this.isOpen();
23616            },
23617            setVal: function setVal(val) {
23618                this.input.setQuery(_.toStr(val));
23619            },
23620            getVal: function getVal() {
23621                return this.input.getQuery();
23622            },
23623            select: function select($selectable) {
23624                var data = this.menu.getSelectableData($selectable);
23625                if (data && !this.eventBus.before("select", data.obj)) {
23626                    this.input.setQuery(data.val, true);
23627                    this.eventBus.trigger("select", data.obj);
23628                    this.close();
23629                    return true;
23630                }
23631                return false;
23632            },
23633            autocomplete: function autocomplete($selectable) {
23634                var query, data, isValid;
23635                query = this.input.getQuery();
23636                data = this.menu.getSelectableData($selectable);
23637                isValid = data && query !== data.val;
23638                if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
23639                    this.input.setQuery(data.val);
23640                    this.eventBus.trigger("autocomplete", data.obj);
23641                    return true;
23642                }
23643                return false;
23644            },
23645            moveCursor: function moveCursor(delta) {
23646                var query, $candidate, data, payload, cancelMove;
23647                query = this.input.getQuery();
23648                $candidate = this.menu.selectableRelativeToCursor(delta);
23649                data = this.menu.getSelectableData($candidate);
23650                payload = data ? data.obj : null;
23651                cancelMove = this._minLengthMet() && this.menu.update(query);
23652                if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
23653                    this.menu.setCursor($candidate);
23654                    if (data) {
23655                        this.input.setInputValue(data.val);
23656                    } else {
23657                        this.input.resetInputValue();
23658                        this._updateHint();
23659                    }
23660                    this.eventBus.trigger("cursorchange", payload);
23661                    return true;
23662                }
23663                return false;
23664            },
23665            destroy: function destroy() {
23666                this.input.destroy();
23667                this.menu.destroy();
23668            }
23669        });
23670        return Typeahead;
23671        function c(ctx) {
23672            var methods = [].slice.call(arguments, 1);
23673            return function() {
23674                var args = [].slice.call(arguments);
23675                _.each(methods, function(method) {
23676                    return ctx[method].apply(ctx, args);
23677                });
23678            };
23679        }
23680    }();
23681    (function() {
23682        "use strict";
23683        var old, keys, methods;
23684        old = $.fn.typeahead;
23685        keys = {
23686            www: "tt-www",
23687            attrs: "tt-attrs",
23688            typeahead: "tt-typeahead"
23689        };
23690        methods = {
23691            initialize: function initialize(o, datasets) {
23692                var www;
23693                datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
23694                o = o || {};
23695                www = WWW(o.classNames);
23696                return this.each(attach);
23697                function attach() {
23698                    var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
23699                    _.each(datasets, function(d) {
23700                        d.highlight = !!o.highlight;
23701                    });
23702                    $input = $(this);
23703                    $wrapper = $(www.html.wrapper);
23704                    $hint = $elOrNull(o.hint);
23705                    $menu = $elOrNull(o.menu);
23706                    defaultHint = o.hint !== false && !$hint;
23707                    defaultMenu = o.menu !== false && !$menu;
23708                    defaultHint && ($hint = buildHintFromInput($input, www));
23709                    defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
23710                    $hint && $hint.val("");
23711                    $input = prepInput($input, www);
23712                    if (defaultHint || defaultMenu) {
23713                        $wrapper.css(www.css.wrapper);
23714                        $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
23715                        $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
23716                    }
23717                    MenuConstructor = defaultMenu ? DefaultMenu : Menu;
23718                    eventBus = new EventBus({
23719                        el: $input
23720                    });
23721                    input = new Input({
23722                        hint: $hint,
23723                        input: $input
23724                    }, www);
23725                    menu = new MenuConstructor({
23726                        node: $menu,
23727                        datasets: datasets
23728                    }, www);
23729                    typeahead = new Typeahead({
23730                        input: input,
23731                        menu: menu,
23732                        eventBus: eventBus,
23733                        minLength: o.minLength
23734                    }, www);
23735                    $input.data(keys.www, www);
23736                    $input.data(keys.typeahead, typeahead);
23737                }
23738            },
23739            isEnabled: function isEnabled() {
23740                var enabled;
23741                ttEach(this.first(), function(t) {
23742                    enabled = t.isEnabled();
23743                });
23744                return enabled;
23745            },
23746            enable: function enable() {
23747                ttEach(this, function(t) {
23748                    t.enable();
23749                });
23750                return this;
23751            },
23752            disable: function disable() {
23753                ttEach(this, function(t) {
23754                    t.disable();
23755                });
23756                return this;
23757            },
23758            isActive: function isActive() {
23759                var active;
23760                ttEach(this.first(), function(t) {
23761                    active = t.isActive();
23762                });
23763                return active;
23764            },
23765            activate: function activate() {
23766                ttEach(this, function(t) {
23767                    t.activate();
23768                });
23769                return this;
23770            },
23771            deactivate: function deactivate() {
23772                ttEach(this, function(t) {
23773                    t.deactivate();
23774                });
23775                return this;
23776            },
23777            isOpen: function isOpen() {
23778                var open;
23779                ttEach(this.first(), function(t) {
23780                    open = t.isOpen();
23781                });
23782                return open;
23783            },
23784            open: function open() {
23785                ttEach(this, function(t) {
23786                    t.open();
23787                });
23788                return this;
23789            },
23790            close: function close() {
23791                ttEach(this, function(t) {
23792                    t.close();
23793                });
23794                return this;
23795            },
23796            select: function select(el) {
23797                var success = false, $el = $(el);
23798                ttEach(this.first(), function(t) {
23799                    success = t.select($el);
23800                });
23801                return success;
23802            },
23803            autocomplete: function autocomplete(el) {
23804                var success = false, $el = $(el);
23805                ttEach(this.first(), function(t) {
23806                    success = t.autocomplete($el);
23807                });
23808                return success;
23809            },
23810            moveCursor: function moveCursoe(delta) {
23811                var success = false;
23812                ttEach(this.first(), function(t) {
23813                    success = t.moveCursor(delta);
23814                });
23815                return success;
23816            },
23817            val: function val(newVal) {
23818                var query;
23819                if (!arguments.length) {
23820                    ttEach(this.first(), function(t) {
23821                        query = t.getVal();
23822                    });
23823                    return query;
23824                } else {
23825                    ttEach(this, function(t) {
23826                        t.setVal(newVal);
23827                    });
23828                    return this;
23829                }
23830            },
23831            destroy: function destroy() {
23832                ttEach(this, function(typeahead, $input) {
23833                    revert($input);
23834                    typeahead.destroy();
23835                });
23836                return this;
23837            }
23838        };
23839        $.fn.typeahead = function(method) {
23840            if (methods[method]) {
23841                return methods[method].apply(this, [].slice.call(arguments, 1));
23842            } else {
23843                return methods.initialize.apply(this, arguments);
23844            }
23845        };
23846        $.fn.typeahead.noConflict = function noConflict() {
23847            $.fn.typeahead = old;
23848            return this;
23849        };
23850        function ttEach($els, fn) {
23851            $els.each(function() {
23852                var $input = $(this), typeahead;
23853                (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
23854            });
23855        }
23856        function buildHintFromInput($input, www) {
23857            return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
23858                autocomplete: "off",
23859                spellcheck: "false",
23860                tabindex: -1
23861            });
23862        }
23863        function prepInput($input, www) {
23864            $input.data(keys.attrs, {
23865                dir: $input.attr("dir"),
23866                autocomplete: $input.attr("autocomplete"),
23867                spellcheck: $input.attr("spellcheck"),
23868                style: $input.attr("style")
23869            });
23870            $input.addClass(www.classes.input).attr({
23871                autocomplete: "off",
23872                spellcheck: false
23873            });
23874            try {
23875                !$input.attr("dir") && $input.attr("dir", "auto");
23876            } catch (e) {}
23877            return $input;
23878        }
23879        function getBackgroundStyles($el) {
23880            return {
23881                backgroundAttachment: $el.css("background-attachment"),
23882                backgroundClip: $el.css("background-clip"),
23883                backgroundColor: $el.css("background-color"),
23884                backgroundImage: $el.css("background-image"),
23885                backgroundOrigin: $el.css("background-origin"),
23886                backgroundPosition: $el.css("background-position"),
23887                backgroundRepeat: $el.css("background-repeat"),
23888                backgroundSize: $el.css("background-size")
23889            };
23890        }
23891        function revert($input) {
23892            var www, $wrapper;
23893            www = $input.data(keys.www);
23894            $wrapper = $input.parent().filter(www.selectors.wrapper);
23895            _.each($input.data(keys.attrs), function(val, key) {
23896                _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
23897            });
23898            $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
23899            if ($wrapper.length) {
23900                $input.detach().insertAfter($wrapper);
23901                $wrapper.remove();
23902            }
23903        }
23904        function $elOrNull(obj) {
23905            var isValid, $el;
23906            isValid = _.isJQuery(obj) || _.isElement(obj);
23907            $el = isValid ? $(obj).first() : [];
23908            return $el.length ? $el : null;
23909        }
23910    })();
23911});
vendor: 47,604 bytes, lines 23911-25541
23911
23912/**!
23913
23914 @license
23915 handlebars v4.0.12
23916
23917Copyright (C) 2011-2017 by Yehuda Katz
23918
23919Permission is hereby granted, free of charge, to any person obtaining a copy
23920of this software and associated documentation files (the "Software"), to deal
23921in the Software without restriction, including without limitation the rights
23922to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23923copies of the Software, and to permit persons to whom the Software is
23924furnished to do so, subject to the following conditions:
23925
23926The above copyright notice and this permission notice shall be included in
23927all copies or substantial portions of the Software.
23928
23929THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23930IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23931FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23932AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23933LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23934OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23935THE SOFTWARE.
23936
23937*/
23938(function webpackUniversalModuleDefinition(root, factory) {
23939	if(typeof exports === 'object' && typeof module === 'object')
23940		module.exports = factory();
23941	else if(typeof define === 'function' && define.amd)
23942		define([], factory);
23943	else if(typeof exports === 'object')
23944		exports["Handlebars"] = factory();
23945	else
23946		root["Handlebars"] = factory();
23947})(this, function() {
23948return /******/ (function(modules) { // webpackBootstrap
23949/******/ 	// The module cache
23950/******/ 	var installedModules = {};
23951
23952/******/ 	// The require function
23953/******/ 	function __webpack_require__(moduleId) {
23954
23955/******/ 		// Check if module is in cache
23956/******/ 		if(installedModules[moduleId])
23957/******/ 			return installedModules[moduleId].exports;
23958
23959/******/ 		// Create a new module (and put it into the cache)
23960/******/ 		var module = installedModules[moduleId] = {
23961/******/ 			exports: {},
23962/******/ 			id: moduleId,
23963/******/ 			loaded: false
23964/******/ 		};
23965
23966/******/ 		// Execute the module function
23967/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
23968
23969/******/ 		// Flag the module as loaded
23970/******/ 		module.loaded = true;
23971
23972/******/ 		// Return the exports of the module
23973/******/ 		return module.exports;
23974/******/ 	}
23975
23976
23977/******/ 	// expose the modules object (__webpack_modules__)
23978/******/ 	__webpack_require__.m = modules;
23979
23980/******/ 	// expose the module cache
23981/******/ 	__webpack_require__.c = installedModules;
23982
23983/******/ 	// __webpack_public_path__
23984/******/ 	__webpack_require__.p = "";
23985
23986/******/ 	// Load entry module and return exports
23987/******/ 	return __webpack_require__(0);
23988/******/ })
23989/************************************************************************/
23990/******/ ([
23991/* 0 */
23992/***/ (function(module, exports, __webpack_require__) {
23993
23994	'use strict';
23995
23996	var _interopRequireDefault = __webpack_require__(1)['default'];
23997
23998	exports.__esModule = true;
23999
24000	var _handlebarsRuntime = __webpack_require__(2);
24001
24002	var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime);
24003
24004	// Compiler imports
24005
24006	var _handlebarsCompilerAst = __webpack_require__(35);
24007
24008	var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst);
24009
24010	var _handlebarsCompilerBase = __webpack_require__(36);
24011
24012	var _handlebarsCompilerCompiler = __webpack_require__(41);
24013
24014	var _handlebarsCompilerJavascriptCompiler = __webpack_require__(42);
24015
24016	var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler);
24017
24018	var _handlebarsCompilerVisitor = __webpack_require__(39);
24019
24020	var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor);
24021
24022	var _handlebarsNoConflict = __webpack_require__(34);
24023
24024	var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
24025
24026	var _create = _handlebarsRuntime2['default'].create;
24027	function create() {
24028	  var hb = _create();
24029
24030	  hb.compile = function (input, options) {
24031	    return _handlebarsCompilerCompiler.compile(input, options, hb);
24032	  };
24033	  hb.precompile = function (input, options) {
24034	    return _handlebarsCompilerCompiler.precompile(input, options, hb);
24035	  };
24036
24037	  hb.AST = _handlebarsCompilerAst2['default'];
24038	  hb.Compiler = _handlebarsCompilerCompiler.Compiler;
24039	  hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default'];
24040	  hb.Parser = _handlebarsCompilerBase.parser;
24041	  hb.parse = _handlebarsCompilerBase.parse;
24042
24043	  return hb;
24044	}
24045
24046	var inst = create();
24047	inst.create = create;
24048
24049	_handlebarsNoConflict2['default'](inst);
24050
24051	inst.Visitor = _handlebarsCompilerVisitor2['default'];
24052
24053	inst['default'] = inst;
24054
24055	exports['default'] = inst;
24056	module.exports = exports['default'];
24057
24058/***/ }),
24059/* 1 */
24060/***/ (function(module, exports) {
24061
24062	"use strict";
24063
24064	exports["default"] = function (obj) {
24065	  return obj && obj.__esModule ? obj : {
24066	    "default": obj
24067	  };
24068	};
24069
24070	exports.__esModule = true;
24071
24072/***/ }),
24073/* 2 */
24074/***/ (function(module, exports, __webpack_require__) {
24075
24076	'use strict';
24077
24078	var _interopRequireWildcard = __webpack_require__(3)['default'];
24079
24080	var _interopRequireDefault = __webpack_require__(1)['default'];
24081
24082	exports.__esModule = true;
24083
24084	var _handlebarsBase = __webpack_require__(4);
24085
24086	var base = _interopRequireWildcard(_handlebarsBase);
24087
24088	// Each of these augment the Handlebars object. No need to setup here.
24089	// (This is done to easily share code between commonjs and browse envs)
24090
24091	var _handlebarsSafeString = __webpack_require__(21);
24092
24093	var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString);
24094
24095	var _handlebarsException = __webpack_require__(6);
24096
24097	var _handlebarsException2 = _interopRequireDefault(_handlebarsException);
24098
24099	var _handlebarsUtils = __webpack_require__(5);
24100
24101	var Utils = _interopRequireWildcard(_handlebarsUtils);
24102
24103	var _handlebarsRuntime = __webpack_require__(22);
24104
24105	var runtime = _interopRequireWildcard(_handlebarsRuntime);
24106
24107	var _handlebarsNoConflict = __webpack_require__(34);
24108
24109	var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict);
24110
24111	// For compatibility and usage outside of module systems, make the Handlebars object a namespace
24112	function create() {
24113	  var hb = new base.HandlebarsEnvironment();
24114
24115	  Utils.extend(hb, base);
24116	  hb.SafeString = _handlebarsSafeString2['default'];
24117	  hb.Exception = _handlebarsException2['default'];
24118	  hb.Utils = Utils;
24119	  hb.escapeExpression = Utils.escapeExpression;
24120
24121	  hb.VM = runtime;
24122	  hb.template = function (spec) {
24123	    return runtime.template(spec, hb);
24124	  };
24125
24126	  return hb;
24127	}
24128
24129	var inst = create();
24130	inst.create = create;
24131
24132	_handlebarsNoConflict2['default'](inst);
24133
24134	inst['default'] = inst;
24135
24136	exports['default'] = inst;
24137	module.exports = exports['default'];
24138
24139/***/ }),
24140/* 3 */
24141/***/ (function(module, exports) {
24142
24143	"use strict";
24144
24145	exports["default"] = function (obj) {
24146	  if (obj && obj.__esModule) {
24147	    return obj;
24148	  } else {
24149	    var newObj = {};
24150
24151	    if (obj != null) {
24152	      for (var key in obj) {
24153	        if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
24154	      }
24155	    }
24156
24157	    newObj["default"] = obj;
24158	    return newObj;
24159	  }
24160	};
24161
24162	exports.__esModule = true;
24163
24164/***/ }),
24165/* 4 */
24166/***/ (function(module, exports, __webpack_require__) {
24167
24168	'use strict';
24169
24170	var _interopRequireDefault = __webpack_require__(1)['default'];
24171
24172	exports.__esModule = true;
24173	exports.HandlebarsEnvironment = HandlebarsEnvironment;
24174
24175	var _utils = __webpack_require__(5);
24176
24177	var _exception = __webpack_require__(6);
24178
24179	var _exception2 = _interopRequireDefault(_exception);
24180
24181	var _helpers = __webpack_require__(10);
24182
24183	var _decorators = __webpack_require__(18);
24184
24185	var _logger = __webpack_require__(20);
24186
24187	var _logger2 = _interopRequireDefault(_logger);
24188
24189	var VERSION = '4.0.12';
24190	exports.VERSION = VERSION;
24191	var COMPILER_REVISION = 7;
24192
24193	exports.COMPILER_REVISION = COMPILER_REVISION;
24194	var REVISION_CHANGES = {
24195	  1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
24196	  2: '== 1.0.0-rc.3',
24197	  3: '== 1.0.0-rc.4',
24198	  4: '== 1.x.x',
24199	  5: '== 2.0.0-alpha.x',
24200	  6: '>= 2.0.0-beta.1',
24201	  7: '>= 4.0.0'
24202	};
24203
24204	exports.REVISION_CHANGES = REVISION_CHANGES;
24205	var objectType = '[object Object]';
24206
24207	function HandlebarsEnvironment(helpers, partials, decorators) {
24208	  this.helpers = helpers || {};
24209	  this.partials = partials || {};
24210	  this.decorators = decorators || {};
24211
24212	  _helpers.registerDefaultHelpers(this);
24213	  _decorators.registerDefaultDecorators(this);
24214	}
24215
24216	HandlebarsEnvironment.prototype = {
24217	  constructor: HandlebarsEnvironment,
24218
24219	  logger: _logger2['default'],
24220	  log: _logger2['default'].log,
24221
24222	  registerHelper: function registerHelper(name, fn) {
24223	    if (_utils.toString.call(name) === objectType) {
24224	      if (fn) {
24225	        throw new _exception2['default']('Arg not supported with multiple helpers');
24226	      }
24227	      _utils.extend(this.helpers, name);
24228	    } else {
24229	      this.helpers[name] = fn;
24230	    }
24231	  },
24232	  unregisterHelper: function unregisterHelper(name) {
24233	    delete this.helpers[name];
24234	  },
24235
24236	  registerPartial: function registerPartial(name, partial) {
24237	    if (_utils.toString.call(name) === objectType) {
24238	      _utils.extend(this.partials, name);
24239	    } else {
24240	      if (typeof partial === 'undefined') {
24241	        throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined');
24242	      }
24243	      this.partials[name] = partial;
24244	    }
24245	  },
24246	  unregisterPartial: function unregisterPartial(name) {
24247	    delete this.partials[name];
24248	  },
24249
24250	  registerDecorator: function registerDecorator(name, fn) {
24251	    if (_utils.toString.call(name) === objectType) {
24252	      if (fn) {
24253	        throw new _exception2['default']('Arg not supported with multiple decorators');
24254	      }
24255	      _utils.extend(this.decorators, name);
24256	    } else {
24257	      this.decorators[name] = fn;
24258	    }
24259	  },
24260	  unregisterDecorator: function unregisterDecorator(name) {
24261	    delete this.decorators[name];
24262	  }
24263	};
24264
24265	var log = _logger2['default'].log;
24266
24267	exports.log = log;
24268	exports.createFrame = _utils.createFrame;
24269	exports.logger = _logger2['default'];
24270
24271/***/ }),
24272/* 5 */
24273/***/ (function(module, exports) {
24274
24275	'use strict';
24276
24277	exports.__esModule = true;
24278	exports.extend = extend;
24279	exports.indexOf = indexOf;
24280	exports.escapeExpression = escapeExpression;
24281	exports.isEmpty = isEmpty;
24282	exports.createFrame = createFrame;
24283	exports.blockParams = blockParams;
24284	exports.appendContextPath = appendContextPath;
24285	var escape = {
24286	  '&': '&amp;',
24287	  '<': '&lt;',
24288	  '>': '&gt;',
24289	  '"': '&quot;',
24290	  "'": '&#x27;',
24291	  '`': '&#x60;',
24292	  '=': '&#x3D;'
24293	};
24294
24295	var badChars = /[&<>"'`=]/g,
24296	    possible = /[&<>"'`=]/;
24297
24298	function escapeChar(chr) {
24299	  return escape[chr];
24300	}
24301
24302	function extend(obj /* , ...source */) {
24303	  for (var i = 1; i < arguments.length; i++) {
24304	    for (var key in arguments[i]) {
24305	      if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
24306	        obj[key] = arguments[i][key];
24307	      }
24308	    }
24309	  }
24310
24311	  return obj;
24312	}
24313
24314	var toString = Object.prototype.toString;
24315
24316	exports.toString = toString;
24317	// Sourced from lodash
24318	// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
24319	/* eslint-disable func-style */
24320	var isFunction = function isFunction(value) {
24321	  return typeof value === 'function';
24322	};
24323	// fallback for older versions of Chrome and Safari
24324	/* istanbul ignore next */
24325	if (isFunction(/x/)) {
24326	  exports.isFunction = isFunction = function (value) {
24327	    return typeof value === 'function' && toString.call(value) === '[object Function]';
24328	  };
24329	}
24330	exports.isFunction = isFunction;
24331
24332	/* eslint-enable func-style */
24333
24334	/* istanbul ignore next */
24335	var isArray = Array.isArray || function (value) {
24336	  return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
24337	};
24338
24339	exports.isArray = isArray;
24340	// Older IE versions do not directly support indexOf so we must implement our own, sadly.
24341
24342	function indexOf(array, value) {
24343	  for (var i = 0, len = array.length; i < len; i++) {
24344	    if (array[i] === value) {
24345	      return i;
24346	    }
24347	  }
24348	  return -1;
24349	}
24350
24351	function escapeExpression(string) {
24352	  if (typeof string !== 'string') {
24353	    // don't escape SafeStrings, since they're already safe
24354	    if (string && string.toHTML) {
24355	      return string.toHTML();
24356	    } else if (string == null) {
24357	      return '';
24358	    } else if (!string) {
24359	      return string + '';
24360	    }
24361
24362	    // Force a string conversion as this will be done by the append regardless and
24363	    // the regex test will do this transparently behind the scenes, causing issues if
24364	    // an object's to string has escaped characters in it.
24365	    string = '' + string;
24366	  }
24367
24368	  if (!possible.test(string)) {
24369	    return string;
24370	  }
24371	  return string.replace(badChars, escapeChar);
24372	}
24373
24374	function isEmpty(value) {
24375	  if (!value && value !== 0) {
24376	    return true;
24377	  } else if (isArray(value) && value.length === 0) {
24378	    return true;
24379	  } else {
24380	    return false;
24381	  }
24382	}
24383
24384	function createFrame(object) {
24385	  var frame = extend({}, object);
24386	  frame._parent = object;
24387	  return frame;
24388	}
24389
24390	function blockParams(params, ids) {
24391	  params.path = ids;
24392	  return params;
24393	}
24394
24395	function appendContextPath(contextPath, id) {
24396	  return (contextPath ? contextPath + '.' : '') + id;
24397	}
24398
24399/***/ }),
24400/* 6 */
24401/***/ (function(module, exports, __webpack_require__) {
24402
24403	'use strict';
24404
24405	var _Object$defineProperty = __webpack_require__(7)['default'];
24406
24407	exports.__esModule = true;
24408
24409	var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
24410
24411	function Exception(message, node) {
24412	  var loc = node && node.loc,
24413	      line = undefined,
24414	      column = undefined;
24415	  if (loc) {
24416	    line = loc.start.line;
24417	    column = loc.start.column;
24418
24419	    message += ' - ' + line + ':' + column;
24420	  }
24421
24422	  var tmp = Error.prototype.constructor.call(this, message);
24423
24424	  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
24425	  for (var idx = 0; idx < errorProps.length; idx++) {
24426	    this[errorProps[idx]] = tmp[errorProps[idx]];
24427	  }
24428
24429	  /* istanbul ignore else */
24430	  if (Error.captureStackTrace) {
24431	    Error.captureStackTrace(this, Exception);
24432	  }
24433
24434	  try {
24435	    if (loc) {
24436	      this.lineNumber = line;
24437
24438	      // Work around issue under safari where we can't directly set the column value
24439	      /* istanbul ignore next */
24440	      if (_Object$defineProperty) {
24441	        Object.defineProperty(this, 'column', {
24442	          value: column,
24443	          enumerable: true
24444	        });
24445	      } else {
24446	        this.column = column;
24447	      }
24448	    }
24449	  } catch (nop) {
24450	    /* Ignore if the browser is very particular */
24451	  }
24452	}
24453
24454	Exception.prototype = new Error();
24455
24456	exports['default'] = Exception;
24457	module.exports = exports['default'];
24458
24459/***/ }),
24460/* 7 */
24461/***/ (function(module, exports, __webpack_require__) {
24462
24463	module.exports = { "default": __webpack_require__(8), __esModule: true };
24464
24465/***/ }),
24466/* 8 */
24467/***/ (function(module, exports, __webpack_require__) {
24468
24469	var $ = __webpack_require__(9);
24470	module.exports = function defineProperty(it, key, desc){
24471	  return $.setDesc(it, key, desc);
24472	};
24473
24474/***/ }),
24475/* 9 */
24476/***/ (function(module, exports) {
24477
24478	var $Object = Object;
24479	module.exports = {
24480	  create:     $Object.create,
24481	  getProto:   $Object.getPrototypeOf,
24482	  isEnum:     {}.propertyIsEnumerable,
24483	  getDesc:    $Object.getOwnPropertyDescriptor,
24484	  setDesc:    $Object.defineProperty,
24485	  setDescs:   $Object.defineProperties,
24486	  getKeys:    $Object.keys,
24487	  getNames:   $Object.getOwnPropertyNames,
24488	  getSymbols: $Object.getOwnPropertySymbols,
24489	  each:       [].forEach
24490	};
24491
24492/***/ }),
24493/* 10 */
24494/***/ (function(module, exports, __webpack_require__) {
24495
24496	'use strict';
24497
24498	var _interopRequireDefault = __webpack_require__(1)['default'];
24499
24500	exports.__esModule = true;
24501	exports.registerDefaultHelpers = registerDefaultHelpers;
24502
24503	var _helpersBlockHelperMissing = __webpack_require__(11);
24504
24505	var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing);
24506
24507	var _helpersEach = __webpack_require__(12);
24508
24509	var _helpersEach2 = _interopRequireDefault(_helpersEach);
24510
24511	var _helpersHelperMissing = __webpack_require__(13);
24512
24513	var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing);
24514
24515	var _helpersIf = __webpack_require__(14);
24516
24517	var _helpersIf2 = _interopRequireDefault(_helpersIf);
24518
24519	var _helpersLog = __webpack_require__(15);
24520
24521	var _helpersLog2 = _interopRequireDefault(_helpersLog);
24522
24523	var _helpersLookup = __webpack_require__(16);
24524
24525	var _helpersLookup2 = _interopRequireDefault(_helpersLookup);
24526
24527	var _helpersWith = __webpack_require__(17);
24528
24529	var _helpersWith2 = _interopRequireDefault(_helpersWith);
24530
24531	function registerDefaultHelpers(instance) {
24532	  _helpersBlockHelperMissing2['default'](instance);
24533	  _helpersEach2['default'](instance);
24534	  _helpersHelperMissing2['default'](instance);
24535	  _helpersIf2['default'](instance);
24536	  _helpersLog2['default'](instance);
24537	  _helpersLookup2['default'](instance);
24538	  _helpersWith2['default'](instance);
24539	}
24540
24541/***/ }),
24542/* 11 */
24543/***/ (function(module, exports, __webpack_require__) {
24544
24545	'use strict';
24546
24547	exports.__esModule = true;
24548
24549	var _utils = __webpack_require__(5);
24550
24551	exports['default'] = function (instance) {
24552	  instance.registerHelper('blockHelperMissing', function (context, options) {
24553	    var inverse = options.inverse,
24554	        fn = options.fn;
24555
24556	    if (context === true) {
24557	      return fn(this);
24558	    } else if (context === false || context == null) {
24559	      return inverse(this);
24560	    } else if (_utils.isArray(context)) {
24561	      if (context.length > 0) {
24562	        if (options.ids) {
24563	          options.ids = [options.name];
24564	        }
24565
24566	        return instance.helpers.each(context, options);
24567	      } else {
24568	        return inverse(this);
24569	      }
24570	    } else {
24571	      if (options.data && options.ids) {
24572	        var data = _utils.createFrame(options.data);
24573	        data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name);
24574	        options = { data: data };
24575	      }
24576
24577	      return fn(context, options);
24578	    }
24579	  });
24580	};
24581
24582	module.exports = exports['default'];
24583
24584/***/ }),
24585/* 12 */
24586/***/ (function(module, exports, __webpack_require__) {
24587
24588	'use strict';
24589
24590	var _interopRequireDefault = __webpack_require__(1)['default'];
24591
24592	exports.__esModule = true;
24593
24594	var _utils = __webpack_require__(5);
24595
24596	var _exception = __webpack_require__(6);
24597
24598	var _exception2 = _interopRequireDefault(_exception);
24599
24600	exports['default'] = function (instance) {
24601	  instance.registerHelper('each', function (context, options) {
24602	    if (!options) {
24603	      throw new _exception2['default']('Must pass iterator to #each');
24604	    }
24605
24606	    var fn = options.fn,
24607	        inverse = options.inverse,
24608	        i = 0,
24609	        ret = '',
24610	        data = undefined,
24611	        contextPath = undefined;
24612
24613	    if (options.data && options.ids) {
24614	      contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
24615	    }
24616
24617	    if (_utils.isFunction(context)) {
24618	      context = context.call(this);
24619	    }
24620
24621	    if (options.data) {
24622	      data = _utils.createFrame(options.data);
24623	    }
24624
24625	    function execIteration(field, index, last) {
24626	      if (data) {
24627	        data.key = field;
24628	        data.index = index;
24629	        data.first = index === 0;
24630	        data.last = !!last;
24631
24632	        if (contextPath) {
24633	          data.contextPath = contextPath + field;
24634	        }
24635	      }
24636
24637	      ret = ret + fn(context[field], {
24638	        data: data,
24639	        blockParams: _utils.blockParams([context[field], field], [contextPath + field, null])
24640	      });
24641	    }
24642
24643	    if (context && typeof context === 'object') {
24644	      if (_utils.isArray(context)) {
24645	        for (var j = context.length; i < j; i++) {
24646	          if (i in context) {
24647	            execIteration(i, i, i === context.length - 1);
24648	          }
24649	        }
24650	      } else {
24651	        var priorKey = undefined;
24652
24653	        for (var key in context) {
24654	          if (context.hasOwnProperty(key)) {
24655	            // We're running the iterations one step out of sync so we can detect
24656	            // the last iteration without have to scan the object twice and create
24657	            // an itermediate keys array.
24658	            if (priorKey !== undefined) {
24659	              execIteration(priorKey, i - 1);
24660	            }
24661	            priorKey = key;
24662	            i++;
24663	          }
24664	        }
24665	        if (priorKey !== undefined) {
24666	          execIteration(priorKey, i - 1, true);
24667	        }
24668	      }
24669	    }
24670
24671	    if (i === 0) {
24672	      ret = inverse(this);
24673	    }
24674
24675	    return ret;
24676	  });
24677	};
24678
24679	module.exports = exports['default'];
24680
24681/***/ }),
24682/* 13 */
24683/***/ (function(module, exports, __webpack_require__) {
24684
24685	'use strict';
24686
24687	var _interopRequireDefault = __webpack_require__(1)['default'];
24688
24689	exports.__esModule = true;
24690
24691	var _exception = __webpack_require__(6);
24692
24693	var _exception2 = _interopRequireDefault(_exception);
24694
24695	exports['default'] = function (instance) {
24696	  instance.registerHelper('helperMissing', function () /* [args, ]options */{
24697	    if (arguments.length === 1) {
24698	      // A missing field in a {{foo}} construct.
24699	      return undefined;
24700	    } else {
24701	      // Someone is actually trying to call something, blow up.
24702	      throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
24703	    }
24704	  });
24705	};
24706
24707	module.exports = exports['default'];
24708
24709/***/ }),
24710/* 14 */
24711/***/ (function(module, exports, __webpack_require__) {
24712
24713	'use strict';
24714
24715	exports.__esModule = true;
24716
24717	var _utils = __webpack_require__(5);
24718
24719	exports['default'] = function (instance) {
24720	  instance.registerHelper('if', function (conditional, options) {
24721	    if (_utils.isFunction(conditional)) {
24722	      conditional = conditional.call(this);
24723	    }
24724
24725	    // Default behavior is to render the positive path if the value is truthy and not empty.
24726	    // The `includeZero` option may be set to treat the condtional as purely not empty based on the
24727	    // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
24728	    if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) {
24729	      return options.inverse(this);
24730	    } else {
24731	      return options.fn(this);
24732	    }
24733	  });
24734
24735	  instance.registerHelper('unless', function (conditional, options) {
24736	    return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash });
24737	  });
24738	};
24739
24740	module.exports = exports['default'];
24741
24742/***/ }),
24743/* 15 */
24744/***/ (function(module, exports) {
24745
24746	'use strict';
24747
24748	exports.__esModule = true;
24749
24750	exports['default'] = function (instance) {
24751	  instance.registerHelper('log', function () /* message, options */{
24752	    var args = [undefined],
24753	        options = arguments[arguments.length - 1];
24754	    for (var i = 0; i < arguments.length - 1; i++) {
24755	      args.push(arguments[i]);
24756	    }
24757
24758	    var level = 1;
24759	    if (options.hash.level != null) {
24760	      level = options.hash.level;
24761	    } else if (options.data && options.data.level != null) {
24762	      level = options.data.level;
24763	    }
24764	    args[0] = level;
24765
24766	    instance.log.apply(instance, args);
24767	  });
24768	};
24769
24770	module.exports = exports['default'];
24771
24772/***/ }),
24773/* 16 */
24774/***/ (function(module, exports) {
24775
24776	'use strict';
24777
24778	exports.__esModule = true;
24779
24780	exports['default'] = function (instance) {
24781	  instance.registerHelper('lookup', function (obj, field) {
24782	    return obj && obj[field];
24783	  });
24784	};
24785
24786	module.exports = exports['default'];
24787
24788/***/ }),
24789/* 17 */
24790/***/ (function(module, exports, __webpack_require__) {
24791
24792	'use strict';
24793
24794	exports.__esModule = true;
24795
24796	var _utils = __webpack_require__(5);
24797
24798	exports['default'] = function (instance) {
24799	  instance.registerHelper('with', function (context, options) {
24800	    if (_utils.isFunction(context)) {
24801	      context = context.call(this);
24802	    }
24803
24804	    var fn = options.fn;
24805
24806	    if (!_utils.isEmpty(context)) {
24807	      var data = options.data;
24808	      if (options.data && options.ids) {
24809	        data = _utils.createFrame(options.data);
24810	        data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]);
24811	      }
24812
24813	      return fn(context, {
24814	        data: data,
24815	        blockParams: _utils.blockParams([context], [data && data.contextPath])
24816	      });
24817	    } else {
24818	      return options.inverse(this);
24819	    }
24820	  });
24821	};
24822
24823	module.exports = exports['default'];
24824
24825/***/ }),
24826/* 18 */
24827/***/ (function(module, exports, __webpack_require__) {
24828
24829	'use strict';
24830
24831	var _interopRequireDefault = __webpack_require__(1)['default'];
24832
24833	exports.__esModule = true;
24834	exports.registerDefaultDecorators = registerDefaultDecorators;
24835
24836	var _decoratorsInline = __webpack_require__(19);
24837
24838	var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline);
24839
24840	function registerDefaultDecorators(instance) {
24841	  _decoratorsInline2['default'](instance);
24842	}
24843
24844/***/ }),
24845/* 19 */
24846/***/ (function(module, exports, __webpack_require__) {
24847
24848	'use strict';
24849
24850	exports.__esModule = true;
24851
24852	var _utils = __webpack_require__(5);
24853
24854	exports['default'] = function (instance) {
24855	  instance.registerDecorator('inline', function (fn, props, container, options) {
24856	    var ret = fn;
24857	    if (!props.partials) {
24858	      props.partials = {};
24859	      ret = function (context, options) {
24860	        // Create a new partials stack frame prior to exec.
24861	        var original = container.partials;
24862	        container.partials = _utils.extend({}, original, props.partials);
24863	        var ret = fn(context, options);
24864	        container.partials = original;
24865	        return ret;
24866	      };
24867	    }
24868
24869	    props.partials[options.args[0]] = options.fn;
24870
24871	    return ret;
24872	  });
24873	};
24874
24875	module.exports = exports['default'];
24876
24877/***/ }),
24878/* 20 */
24879/***/ (function(module, exports, __webpack_require__) {
24880
24881	'use strict';
24882
24883	exports.__esModule = true;
24884
24885	var _utils = __webpack_require__(5);
24886
24887	var logger = {
24888	  methodMap: ['debug', 'info', 'warn', 'error'],
24889	  level: 'info',
24890
24891	  // Maps a given level value to the `methodMap` indexes above.
24892	  lookupLevel: function lookupLevel(level) {
24893	    if (typeof level === 'string') {
24894	      var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase());
24895	      if (levelMap >= 0) {
24896	        level = levelMap;
24897	      } else {
24898	        level = parseInt(level, 10);
24899	      }
24900	    }
24901
24902	    return level;
24903	  },
24904
24905	  // Can be overridden in the host environment
24906	  log: function log(level) {
24907	    level = logger.lookupLevel(level);
24908
24909	    if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) {
24910	      var method = logger.methodMap[level];
24911	      if (!console[method]) {
24912	        // eslint-disable-line no-console
24913	        method = 'log';
24914	      }
24915
24916	      for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
24917	        message[_key - 1] = arguments[_key];
24918	      }
24919
24920	      console[method].apply(console, message); // eslint-disable-line no-console
24921	    }
24922	  }
24923	};
24924
24925	exports['default'] = logger;
24926	module.exports = exports['default'];
24927
24928/***/ }),
24929/* 21 */
24930/***/ (function(module, exports) {
24931
24932	// Build out our basic SafeString type
24933	'use strict';
24934
24935	exports.__esModule = true;
24936	function SafeString(string) {
24937	  this.string = string;
24938	}
24939
24940	SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
24941	  return '' + this.string;
24942	};
24943
24944	exports['default'] = SafeString;
24945	module.exports = exports['default'];
24946
24947/***/ }),
24948/* 22 */
24949/***/ (function(module, exports, __webpack_require__) {
24950
24951	'use strict';
24952
24953	var _Object$seal = __webpack_require__(23)['default'];
24954
24955	var _interopRequireWildcard = __webpack_require__(3)['default'];
24956
24957	var _interopRequireDefault = __webpack_require__(1)['default'];
24958
24959	exports.__esModule = true;
24960	exports.checkRevision = checkRevision;
24961	exports.template = template;
24962	exports.wrapProgram = wrapProgram;
24963	exports.resolvePartial = resolvePartial;
24964	exports.invokePartial = invokePartial;
24965	exports.noop = noop;
24966
24967	var _utils = __webpack_require__(5);
24968
24969	var Utils = _interopRequireWildcard(_utils);
24970
24971	var _exception = __webpack_require__(6);
24972
24973	var _exception2 = _interopRequireDefault(_exception);
24974
24975	var _base = __webpack_require__(4);
24976
24977	function checkRevision(compilerInfo) {
24978	  var compilerRevision = compilerInfo && compilerInfo[0] || 1,
24979	      currentRevision = _base.COMPILER_REVISION;
24980
24981	  if (compilerRevision !== currentRevision) {
24982	    if (compilerRevision < currentRevision) {
24983	      var runtimeVersions = _base.REVISION_CHANGES[currentRevision],
24984	          compilerVersions = _base.REVISION_CHANGES[compilerRevision];
24985	      throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
24986	    } else {
24987	      // Use the embedded version info since the runtime doesn't know about this revision yet
24988	      throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
24989	    }
24990	  }
24991	}
24992
24993	function template(templateSpec, env) {
24994	  /* istanbul ignore next */
24995	  if (!env) {
24996	    throw new _exception2['default']('No environment passed to template');
24997	  }
24998	  if (!templateSpec || !templateSpec.main) {
24999	    throw new _exception2['default']('Unknown template object: ' + typeof templateSpec);
25000	  }
25001
25002	  templateSpec.main.decorator = templateSpec.main_d;
25003
25004	  // Note: Using env.VM references rather than local var references throughout this section to allow
25005	  // for external users to override these as psuedo-supported APIs.
25006	  env.VM.checkRevision(templateSpec.compiler);
25007
25008	  function invokePartialWrapper(partial, context, options) {
25009	    if (options.hash) {
25010	      context = Utils.extend({}, context, options.hash);
25011	      if (options.ids) {
25012	        options.ids[0] = true;
25013	      }
25014	    }
25015
25016	    partial = env.VM.resolvePartial.call(this, partial, context, options);
25017	    var result = env.VM.invokePartial.call(this, partial, context, options);
25018
25019	    if (result == null && env.compile) {
25020	      options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
25021	      result = options.partials[options.name](context, options);
25022	    }
25023	    if (result != null) {
25024	      if (options.indent) {
25025	        var lines = result.split('\n');
25026	        for (var i = 0, l = lines.length; i < l; i++) {
25027	          if (!lines[i] && i + 1 === l) {
25028	            break;
25029	          }
25030
25031	          lines[i] = options.indent + lines[i];
25032	        }
25033	        result = lines.join('\n');
25034	      }
25035	      return result;
25036	    } else {
25037	      throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
25038	    }
25039	  }
25040
25041	  // Just add water
25042	  var container = {
25043	    strict: function strict(obj, name) {
25044	      if (!(name in obj)) {
25045	        throw new _exception2['default']('"' + name + '" not defined in ' + obj);
25046	      }
25047	      return obj[name];
25048	    },
25049	    lookup: function lookup(depths, name) {
25050	      var len = depths.length;
25051	      for (var i = 0; i < len; i++) {
25052	        if (depths[i] && depths[i][name] != null) {
25053	          return depths[i][name];
25054	        }
25055	      }
25056	    },
25057	    lambda: function lambda(current, context) {
25058	      return typeof current === 'function' ? current.call(context) : current;
25059	    },
25060
25061	    escapeExpression: Utils.escapeExpression,
25062	    invokePartial: invokePartialWrapper,
25063
25064	    fn: function fn(i) {
25065	      var ret = templateSpec[i];
25066	      ret.decorator = templateSpec[i + '_d'];
25067	      return ret;
25068	    },
25069
25070	    programs: [],
25071	    program: function program(i, data, declaredBlockParams, blockParams, depths) {
25072	      var programWrapper = this.programs[i],
25073	          fn = this.fn(i);
25074	      if (data || depths || blockParams || declaredBlockParams) {
25075	        programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
25076	      } else if (!programWrapper) {
25077	        programWrapper = this.programs[i] = wrapProgram(this, i, fn);
25078	      }
25079	      return programWrapper;
25080	    },
25081
25082	    data: function data(value, depth) {
25083	      while (value && depth--) {
25084	        value = value._parent;
25085	      }
25086	      return value;
25087	    },
25088	    merge: function merge(param, common) {
25089	      var obj = param || common;
25090
25091	      if (param && common && param !== common) {
25092	        obj = Utils.extend({}, common, param);
25093	      }
25094
25095	      return obj;
25096	    },
25097	    // An empty object to use as replacement for null-contexts
25098	    nullContext: _Object$seal({}),
25099
25100	    noop: env.VM.noop,
25101	    compilerInfo: templateSpec.compiler
25102	  };
25103
25104	  function ret(context) {
25105	    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
25106
25107	    var data = options.data;
25108
25109	    ret._setup(options);
25110	    if (!options.partial && templateSpec.useData) {
25111	      data = initData(context, data);
25112	    }
25113	    var depths = undefined,
25114	        blockParams = templateSpec.useBlockParams ? [] : undefined;
25115	    if (templateSpec.useDepths) {
25116	      if (options.depths) {
25117	        depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
25118	      } else {
25119	        depths = [context];
25120	      }
25121	    }
25122
25123	    function main(context /*, options*/) {
25124	      return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
25125	    }
25126	    main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams);
25127	    return main(context, options);
25128	  }
25129	  ret.isTop = true;
25130
25131	  ret._setup = function (options) {
25132	    if (!options.partial) {
25133	      container.helpers = container.merge(options.helpers, env.helpers);
25134
25135	      if (templateSpec.usePartial) {
25136	        container.partials = container.merge(options.partials, env.partials);
25137	      }
25138	      if (templateSpec.usePartial || templateSpec.useDecorators) {
25139	        container.decorators = container.merge(options.decorators, env.decorators);
25140	      }
25141	    } else {
25142	      container.helpers = options.helpers;
25143	      container.partials = options.partials;
25144	      container.decorators = options.decorators;
25145	    }
25146	  };
25147
25148	  ret._child = function (i, data, blockParams, depths) {
25149	    if (templateSpec.useBlockParams && !blockParams) {
25150	      throw new _exception2['default']('must pass block params');
25151	    }
25152	    if (templateSpec.useDepths && !depths) {
25153	      throw new _exception2['default']('must pass parent depths');
25154	    }
25155
25156	    return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
25157	  };
25158	  return ret;
25159	}
25160
25161	function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
25162	  function prog(context) {
25163	    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
25164
25165	    var currentDepths = depths;
25166	    if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) {
25167	      currentDepths = [context].concat(depths);
25168	    }
25169
25170	    return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths);
25171	  }
25172
25173	  prog = executeDecorators(fn, prog, container, depths, data, blockParams);
25174
25175	  prog.program = i;
25176	  prog.depth = depths ? depths.length : 0;
25177	  prog.blockParams = declaredBlockParams || 0;
25178	  return prog;
25179	}
25180
25181	function resolvePartial(partial, context, options) {
25182	  if (!partial) {
25183	    if (options.name === '@partial-block') {
25184	      partial = options.data['partial-block'];
25185	    } else {
25186	      partial = options.partials[options.name];
25187	    }
25188	  } else if (!partial.call && !options.name) {
25189	    // This is a dynamic partial that returned a string
25190	    options.name = partial;
25191	    partial = options.partials[partial];
25192	  }
25193	  return partial;
25194	}
25195
25196	function invokePartial(partial, context, options) {
25197	  // Use the current closure context to save the partial-block if this partial
25198	  var currentPartialBlock = options.data && options.data['partial-block'];
25199	  options.partial = true;
25200	  if (options.ids) {
25201	    options.data.contextPath = options.ids[0] || options.data.contextPath;
25202	  }
25203
25204	  var partialBlock = undefined;
25205	  if (options.fn && options.fn !== noop) {
25206	    (function () {
25207	      options.data = _base.createFrame(options.data);
25208	      // Wrapper function to get access to currentPartialBlock from the closure
25209	      var fn = options.fn;
25210	      partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) {
25211	        var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
25212
25213	        // Restore the partial-block from the closure for the execution of the block
25214	        // i.e. the part inside the block of the partial call.
25215	        options.data = _base.createFrame(options.data);
25216	        options.data['partial-block'] = currentPartialBlock;
25217	        return fn(context, options);
25218	      };
25219	      if (fn.partials) {
25220	        options.partials = Utils.extend({}, options.partials, fn.partials);
25221	      }
25222	    })();
25223	  }
25224
25225	  if (partial === undefined && partialBlock) {
25226	    partial = partialBlock;
25227	  }
25228
25229	  if (partial === undefined) {
25230	    throw new _exception2['default']('The partial ' + options.name + ' could not be found');
25231	  } else if (partial instanceof Function) {
25232	    return partial(context, options);
25233	  }
25234	}
25235
25236	function noop() {
25237	  return '';
25238	}
25239
25240	function initData(context, data) {
25241	  if (!data || !('root' in data)) {
25242	    data = data ? _base.createFrame(data) : {};
25243	    data.root = context;
25244	  }
25245	  return data;
25246	}
25247
25248	function executeDecorators(fn, prog, container, depths, data, blockParams) {
25249	  if (fn.decorator) {
25250	    var props = {};
25251	    prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths);
25252	    Utils.extend(prog, props);
25253	  }
25254	  return prog;
25255	}
25256
25257/***/ }),
25258/* 23 */
25259/***/ (function(module, exports, __webpack_require__) {
25260
25261	module.exports = { "default": __webpack_require__(24), __esModule: true };
25262
25263/***/ }),
25264/* 24 */
25265/***/ (function(module, exports, __webpack_require__) {
25266
25267	__webpack_require__(25);
25268	module.exports = __webpack_require__(30).Object.seal;
25269
25270/***/ }),
25271/* 25 */
25272/***/ (function(module, exports, __webpack_require__) {
25273
25274	// 19.1.2.17 Object.seal(O)
25275	var isObject = __webpack_require__(26);
25276
25277	__webpack_require__(27)('seal', function($seal){
25278	  return function seal(it){
25279	    return $seal && isObject(it) ? $seal(it) : it;
25280	  };
25281	});
25282
25283/***/ }),
25284/* 26 */
25285/***/ (function(module, exports) {
25286
25287	module.exports = function(it){
25288	  return typeof it === 'object' ? it !== null : typeof it === 'function';
25289	};
25290
25291/***/ }),
25292/* 27 */
25293/***/ (function(module, exports, __webpack_require__) {
25294
25295	// most Object methods by ES6 should accept primitives
25296	var $export = __webpack_require__(28)
25297	  , core    = __webpack_require__(30)
25298	  , fails   = __webpack_require__(33);
25299	module.exports = function(KEY, exec){
25300	  var fn  = (core.Object || {})[KEY] || Object[KEY]
25301	    , exp = {};
25302	  exp[KEY] = exec(fn);
25303	  $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp);
25304	};
25305
25306/***/ }),
25307/* 28 */
25308/***/ (function(module, exports, __webpack_require__) {
25309
25310	var global    = __webpack_require__(29)
25311	  , core      = __webpack_require__(30)
25312	  , ctx       = __webpack_require__(31)
25313	  , PROTOTYPE = 'prototype';
25314
25315	var $export = function(type, name, source){
25316	  var IS_FORCED = type & $export.F
25317	    , IS_GLOBAL = type & $export.G
25318	    , IS_STATIC = type & $export.S
25319	    , IS_PROTO  = type & $export.P
25320	    , IS_BIND   = type & $export.B
25321	    , IS_WRAP   = type & $export.W
25322	    , exports   = IS_GLOBAL ? core : core[name] || (core[name] = {})
25323	    , target    = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]
25324	    , key, own, out;
25325	  if(IS_GLOBAL)source = name;
25326	  for(key in source){
25327	    // contains in native
25328	    own = !IS_FORCED && target && key in target;
25329	    if(own && key in exports)continue;
25330	    // export native or passed
25331	    out = own ? target[key] : source[key];
25332	    // prevent global pollution for namespaces
25333	    exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]
25334	    // bind timers to global for call from export context
25335	    : IS_BIND && own ? ctx(out, global)
25336	    // wrap global constructors for prevent change them in library
25337	    : IS_WRAP && target[key] == out ? (function(C){
25338	      var F = function(param){
25339	        return this instanceof C ? new C(param) : C(param);
25340	      };
25341	      F[PROTOTYPE] = C[PROTOTYPE];
25342	      return F;
25343	    // make static versions for prototype methods
25344	    })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
25345	    if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out;
25346	  }
25347	};
25348	// type bitmap
25349	$export.F = 1;  // forced
25350	$export.G = 2;  // global
25351	$export.S = 4;  // static
25352	$export.P = 8;  // proto
25353	$export.B = 16; // bind
25354	$export.W = 32; // wrap
25355	module.exports = $export;
25356
25357/***/ }),
25358/* 29 */
25359/***/ (function(module, exports) {
25360
25361	// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
25362	var global = module.exports = typeof window != 'undefined' && window.Math == Math
25363	  ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
25364	if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
25365
25366/***/ }),
25367/* 30 */
25368/***/ (function(module, exports) {
25369
25370	var core = module.exports = {version: '1.2.6'};
25371	if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
25372
25373/***/ }),
25374/* 31 */
25375/***/ (function(module, exports, __webpack_require__) {
25376
25377	// optional / simple context binding
25378	var aFunction = __webpack_require__(32);
25379	module.exports = function(fn, that, length){
25380	  aFunction(fn);
25381	  if(that === undefined)return fn;
25382	  switch(length){
25383	    case 1: return function(a){
25384	      return fn.call(that, a);
25385	    };
25386	    case 2: return function(a, b){
25387	      return fn.call(that, a, b);
25388	    };
25389	    case 3: return function(a, b, c){
25390	      return fn.call(that, a, b, c);
25391	    };
25392	  }
25393	  return function(/* ...args */){
25394	    return fn.apply(that, arguments);
25395	  };
25396	};
25397
25398/***/ }),
25399/* 32 */
25400/***/ (function(module, exports) {
25401
25402	module.exports = function(it){
25403	  if(typeof it != 'function')throw TypeError(it + ' is not a function!');
25404	  return it;
25405	};
25406
25407/***/ }),
25408/* 33 */
25409/***/ (function(module, exports) {
25410
25411	module.exports = function(exec){
25412	  try {
25413	    return !!exec();
25414	  } catch(e){
25415	    return true;
25416	  }
25417	};
25418
25419/***/ }),
25420/* 34 */
25421/***/ (function(module, exports) {
25422
25423	/* WEBPACK VAR INJECTION */(function(global) {/* global window */
25424	'use strict';
25425
25426	exports.__esModule = true;
25427
25428	exports['default'] = function (Handlebars) {
25429	  /* istanbul ignore next */
25430	  var root = typeof global !== 'undefined' ? global : window,
25431	      $Handlebars = root.Handlebars;
25432	  /* istanbul ignore next */
25433	  Handlebars.noConflict = function () {
25434	    if (root.Handlebars === Handlebars) {
25435	      root.Handlebars = $Handlebars;
25436	    }
25437	    return Handlebars;
25438	  };
25439	};
25440
25441	module.exports = exports['default'];
25442	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
25443
25444/***/ }),
25445/* 35 */
25446/***/ (function(module, exports) {
25447
25448	'use strict';
25449
25450	exports.__esModule = true;
25451	var AST = {
25452	  // Public API used to evaluate derived attributes regarding AST nodes
25453	  helpers: {
25454	    // a mustache is definitely a helper if:
25455	    // * it is an eligible helper, and
25456	    // * it has at least one parameter or hash segment
25457	    helperExpression: function helperExpression(node) {
25458	      return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash);
25459	    },
25460
25461	    scopedId: function scopedId(path) {
25462	      return (/^\.|this\b/.test(path.original)
25463	      );
25464	    },
25465
25466	    // an ID is simple if it only has one part, and that part is not
25467	    // `..` or `this`.
25468	    simpleId: function simpleId(path) {
25469	      return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
25470	    }
25471	  }
25472	};
25473
25474	// Must be exported as an object rather than the root of the module as the jison lexer
25475	// must modify the object to operate properly.
25476	exports['default'] = AST;
25477	module.exports = exports['default'];
25478
25479/***/ }),
25480/* 36 */
25481/***/ (function(module, exports, __webpack_require__) {
25482
25483	'use strict';
25484
25485	var _interopRequireDefault = __webpack_require__(1)['default'];
25486
25487	var _interopRequireWildcard = __webpack_require__(3)['default'];
25488
25489	exports.__esModule = true;
25490	exports.parse = parse;
25491
25492	var _parser = __webpack_require__(37);
25493
25494	var _parser2 = _interopRequireDefault(_parser);
25495
25496	var _whitespaceControl = __webpack_require__(38);
25497
25498	var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl);
25499
25500	var _helpers = __webpack_require__(40);
25501
25502	var Helpers = _interopRequireWildcard(_helpers);
25503
25504	var _utils = __webpack_require__(5);
25505
25506	exports.parser = _parser2['default'];
25507
25508	var yy = {};
25509	_utils.extend(yy, Helpers);
25510
25511	function parse(input, options) {
25512	  // Just return if an already-compiled AST was passed in.
25513	  if (input.type === 'Program') {
25514	    return input;
25515	  }
25516
25517	  _parser2['default'].yy = yy;
25518
25519	  // Altering the shared object here, but this is ok as parser is a sync operation
25520	  yy.locInfo = function (locInfo) {
25521	    return new yy.SourceLocation(options && options.srcName, locInfo);
25522	  };
25523
25524	  var strip = new _whitespaceControl2['default'](options);
25525	  return strip.accept(_parser2['default'].parse(input));
25526	}
25527
25528/***/ }),
25529/* 37 */
25530/***/ (function(module, exports) {
25531
25532	// File ignored in coverage tests via setting in .istanbul.yml
25533	/* Jison generated parser */
25534	"use strict";
25535
25536	exports.__esModule = true;
25537	var handlebars = (function () {
25538	    var parser = { trace: function trace() {},
25539	        yy: {},
25540	        symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 },
25541	        terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 
vendor: 26,541 bytes, lines 25541-25797
2554118: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" },
25542	        productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]],
25543	        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$
25544	        /*``*/) {
25545
25546	            var $0 = $$.length - 1;
25547	            switch (yystate) {
25548	                case 1:
25549	                    return $$[$0 - 1];
25550	                    break;
25551	                case 2:
25552	                    this.$ = yy.prepareProgram($$[$0]);
25553	                    break;
25554	                case 3:
25555	                    this.$ = $$[$0];
25556	                    break;
25557	                case 4:
25558	                    this.$ = $$[$0];
25559	                    break;
25560	                case 5:
25561	                    this.$ = $$[$0];
25562	                    break;
25563	                case 6:
25564	                    this.$ = $$[$0];
25565	                    break;
25566	                case 7:
25567	                    this.$ = $$[$0];
25568	                    break;
25569	                case 8:
25570	                    this.$ = $$[$0];
25571	                    break;
25572	                case 9:
25573	                    this.$ = {
25574	                        type: 'CommentStatement',
25575	                        value: yy.stripComment($$[$0]),
25576	                        strip: yy.stripFlags($$[$0], $$[$0]),
25577	                        loc: yy.locInfo(this._$)
25578	                    };
25579
25580	                    break;
25581	                case 10:
25582	                    this.$ = {
25583	                        type: 'ContentStatement',
25584	                        original: $$[$0],
25585	                        value: $$[$0],
25586	                        loc: yy.locInfo(this._$)
25587	                    };
25588
25589	                    break;
25590	                case 11:
25591	                    this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
25592	                    break;
25593	                case 12:
25594	                    this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] };
25595	                    break;
25596	                case 13:
25597	                    this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$);
25598	                    break;
25599	                case 14:
25600	                    this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$);
25601	                    break;
25602	                case 15:
25603	                    this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
25604	                    break;
25605	                case 16:
25606	                    this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
25607	                    break;
25608	                case 17:
25609	                    this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
25610	                    break;
25611	                case 18:
25612	                    this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] };
25613	                    break;
25614	                case 19:
25615	                    var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$),
25616	                        program = yy.prepareProgram([inverse], $$[$0 - 1].loc);
25617	                    program.chained = true;
25618
25619	                    this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true };
25620
25621	                    break;
25622	                case 20:
25623	                    this.$ = $$[$0];
25624	                    break;
25625	                case 21:
25626	                    this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) };
25627	                    break;
25628	                case 22:
25629	                    this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
25630	                    break;
25631	                case 23:
25632	                    this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
25633	                    break;
25634	                case 24:
25635	                    this.$ = {
25636	                        type: 'PartialStatement',
25637	                        name: $$[$0 - 3],
25638	                        params: $$[$0 - 2],
25639	                        hash: $$[$0 - 1],
25640	                        indent: '',
25641	                        strip: yy.stripFlags($$[$0 - 4], $$[$0]),
25642	                        loc: yy.locInfo(this._$)
25643	                    };
25644
25645	                    break;
25646	                case 25:
25647	                    this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
25648	                    break;
25649	                case 26:
25650	                    this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) };
25651	                    break;
25652	                case 27:
25653	                    this.$ = $$[$0];
25654	                    break;
25655	                case 28:
25656	                    this.$ = $$[$0];
25657	                    break;
25658	                case 29:
25659	                    this.$ = {
25660	                        type: 'SubExpression',
25661	                        path: $$[$0 - 3],
25662	                        params: $$[$0 - 2],
25663	                        hash: $$[$0 - 1],
25664	                        loc: yy.locInfo(this._$)
25665	                    };
25666
25667	                    break;
25668	                case 30:
25669	                    this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) };
25670	                    break;
25671	                case 31:
25672	                    this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) };
25673	                    break;
25674	                case 32:
25675	                    this.$ = yy.id($$[$0 - 1]);
25676	                    break;
25677	                case 33:
25678	                    this.$ = $$[$0];
25679	                    break;
25680	                case 34:
25681	                    this.$ = $$[$0];
25682	                    break;
25683	                case 35:
25684	                    this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) };
25685	                    break;
25686	                case 36:
25687	                    this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) };
25688	                    break;
25689	                case 37:
25690	                    this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) };
25691	                    break;
25692	                case 38:
25693	                    this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) };
25694	                    break;
25695	                case 39:
25696	                    this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) };
25697	                    break;
25698	                case 40:
25699	                    this.$ = $$[$0];
25700	                    break;
25701	                case 41:
25702	                    this.$ = $$[$0];
25703	                    break;
25704	                case 42:
25705	                    this.$ = yy.preparePath(true, $$[$0], this._$);
25706	                    break;
25707	                case 43:
25708	                    this.$ = yy.preparePath(false, $$[$0], this._$);
25709	                    break;
25710	                case 44:
25711	                    $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2];
25712	                    break;
25713	                case 45:
25714	                    this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }];
25715	                    break;
25716	                case 46:
25717	                    this.$ = [];
25718	                    break;
25719	                case 47:
25720	                    $$[$0 - 1].push($$[$0]);
25721	                    break;
25722	                case 48:
25723	                    this.$ = [$$[$0]];
25724	                    break;
25725	                case 49:
25726	                    $$[$0 - 1].push($$[$0]);
25727	                    break;
25728	                case 50:
25729	                    this.$ = [];
25730	                    break;
25731	                case 51:
25732	                    $$[$0 - 1].push($$[$0]);
25733	                    break;
25734	                case 58:
25735	                    this.$ = [];
25736	                    break;
25737	                case 59:
25738	                    $$[$0 - 1].push($$[$0]);
25739	                    break;
25740	                case 64:
25741	                    this.$ = [];
25742	                    break;
25743	                case 65:
25744	                    $$[$0 - 1].push($$[$0]);
25745	                    break;
25746	                case 70:
25747	                    this.$ = [];
25748	                    break;
25749	                case 71:
25750	                    $$[$0 - 1].push($$[$0]);
25751	                    break;
25752	                case 78:
25753	                    this.$ = [];
25754	                    break;
25755	                case 79:
25756	                    $$[$0 - 1].push($$[$0]);
25757	                    break;
25758	                case 82:
25759	                    this.$ = [];
25760	                    break;
25761	                case 83:
25762	                    $$[$0 - 1].push($$[$0]);
25763	                    break;
25764	                case 86:
25765	                    this.$ = [];
25766	                    break;
25767	                case 87:
25768	                    $$[$0 - 1].push($$[$0]);
25769	                    break;
25770	                case 90:
25771	                    this.$ = [];
25772	                    break;
25773	                case 91:
25774	                    $$[$0 - 1].push($$[$0]);
25775	                    break;
25776	                case 94:
25777	                    this.$ = [];
25778	                    break;
25779	                case 95:
25780	                    $$[$0 - 1].push($$[$0]);
25781	                    break;
25782	                case 98:
25783	                    this.$ = [$$[$0]];
25784	                    break;
25785	                case 99:
25786	                    $$[$0 - 1].push($$[$0]);
25787	                    break;
25788	                case 100:
25789	                    this.$ = [$$[$0]];
25790	                    break;
25791	                case 101:
25792	                    $$[$0 - 1].push($$[$0]);
25793	                    break;
25794	            }
25795	        },
25796	        table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }],
25797	        defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97
25797], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137
vendor: 13,423 bytes, lines 25797-26081
25797: [2, 32] },
25798	        parseError: function parseError(str, hash) {
25799	            throw new Error(str);
25800	        },
25801	        parse: function parse(input) {
25802	            var self = this,
25803	                stack = [0],
25804	                vstack = [null],
25805	                lstack = [],
25806	                table = this.table,
25807	                yytext = "",
25808	                yylineno = 0,
25809	                yyleng = 0,
25810	                recovering = 0,
25811	                TERROR = 2,
25812	                EOF = 1;
25813	            this.lexer.setInput(input);
25814	            this.lexer.yy = this.yy;
25815	            this.yy.lexer = this.lexer;
25816	            this.yy.parser = this;
25817	            if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {};
25818	            var yyloc = this.lexer.yylloc;
25819	            lstack.push(yyloc);
25820	            var ranges = this.lexer.options && this.lexer.options.ranges;
25821	            if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError;
25822	            function popStack(n) {
25823	                stack.length = stack.length - 2 * n;
25824	                vstack.length = vstack.length - n;
25825	                lstack.length = lstack.length - n;
25826	            }
25827	            function lex() {
25828	                var token;
25829	                token = self.lexer.lex() || 1;
25830	                if (typeof token !== "number") {
25831	                    token = self.symbols_[token] || token;
25832	                }
25833	                return token;
25834	            }
25835	            var symbol,
25836	                preErrorSymbol,
25837	                state,
25838	                action,
25839	                a,
25840	                r,
25841	                yyval = {},
25842	                p,
25843	                len,
25844	                newState,
25845	                expected;
25846	            while (true) {
25847	                state = stack[stack.length - 1];
25848	                if (this.defaultActions[state]) {
25849	                    action = this.defaultActions[state];
25850	                } else {
25851	                    if (symbol === null || typeof symbol == "undefined") {
25852	                        symbol = lex();
25853	                    }
25854	                    action = table[state] && table[state][symbol];
25855	                }
25856	                if (typeof action === "undefined" || !action.length || !action[0]) {
25857	                    var errStr = "";
25858	                    if (!recovering) {
25859	                        expected = [];
25860	                        for (p in table[state]) if (this.terminals_[p] && p > 2) {
25861	                            expected.push("'" + this.terminals_[p] + "'");
25862	                        }
25863	                        if (this.lexer.showPosition) {
25864	                            errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
25865	                        } else {
25866	                            errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
25867	                        }
25868	                        this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
25869	                    }
25870	                }
25871	                if (action[0] instanceof Array && action.length > 1) {
25872	                    throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
25873	                }
25874	                switch (action[0]) {
25875	                    case 1:
25876	                        stack.push(symbol);
25877	                        vstack.push(this.lexer.yytext);
25878	                        lstack.push(this.lexer.yylloc);
25879	                        stack.push(action[1]);
25880	                        symbol = null;
25881	                        if (!preErrorSymbol) {
25882	                            yyleng = this.lexer.yyleng;
25883	                            yytext = this.lexer.yytext;
25884	                            yylineno = this.lexer.yylineno;
25885	                            yyloc = this.lexer.yylloc;
25886	                            if (recovering > 0) recovering--;
25887	                        } else {
25888	                            symbol = preErrorSymbol;
25889	                            preErrorSymbol = null;
25890	                        }
25891	                        break;
25892	                    case 2:
25893	                        len = this.productions_[action[1]][1];
25894	                        yyval.$ = vstack[vstack.length - len];
25895	                        yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column };
25896	                        if (ranges) {
25897	                            yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
25898	                        }
25899	                        r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
25900	                        if (typeof r !== "undefined") {
25901	                            return r;
25902	                        }
25903	                        if (len) {
25904	                            stack = stack.slice(0, -1 * len * 2);
25905	                            vstack = vstack.slice(0, -1 * len);
25906	                            lstack = lstack.slice(0, -1 * len);
25907	                        }
25908	                        stack.push(this.productions_[action[1]][0]);
25909	                        vstack.push(yyval.$);
25910	                        lstack.push(yyval._$);
25911	                        newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
25912	                        stack.push(newState);
25913	                        break;
25914	                    case 3:
25915	                        return true;
25916	                }
25917	            }
25918	            return true;
25919	        }
25920	    };
25921	    /* Jison generated lexer */
25922	    var lexer = (function () {
25923	        var lexer = { EOF: 1,
25924	            parseError: function parseError(str, hash) {
25925	                if (this.yy.parser) {
25926	                    this.yy.parser.parseError(str, hash);
25927	                } else {
25928	                    throw new Error(str);
25929	                }
25930	            },
25931	            setInput: function setInput(input) {
25932	                this._input = input;
25933	                this._more = this._less = this.done = false;
25934	                this.yylineno = this.yyleng = 0;
25935	                this.yytext = this.matched = this.match = '';
25936	                this.conditionStack = ['INITIAL'];
25937	                this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
25938	                if (this.options.ranges) this.yylloc.range = [0, 0];
25939	                this.offset = 0;
25940	                return this;
25941	            },
25942	            input: function input() {
25943	                var ch = this._input[0];
25944	                this.yytext += ch;
25945	                this.yyleng++;
25946	                this.offset++;
25947	                this.match += ch;
25948	                this.matched += ch;
25949	                var lines = ch.match(/(?:\r\n?|\n).*/g);
25950	                if (lines) {
25951	                    this.yylineno++;
25952	                    this.yylloc.last_line++;
25953	                } else {
25954	                    this.yylloc.last_column++;
25955	                }
25956	                if (this.options.ranges) this.yylloc.range[1]++;
25957
25958	                this._input = this._input.slice(1);
25959	                return ch;
25960	            },
25961	            unput: function unput(ch) {
25962	                var len = ch.length;
25963	                var lines = ch.split(/(?:\r\n?|\n)/g);
25964
25965	                this._input = ch + this._input;
25966	                this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
25967	                //this.yyleng -= len;
25968	                this.offset -= len;
25969	                var oldLines = this.match.split(/(?:\r\n?|\n)/g);
25970	                this.match = this.match.substr(0, this.match.length - 1);
25971	                this.matched = this.matched.substr(0, this.matched.length - 1);
25972
25973	                if (lines.length - 1) this.yylineno -= lines.length - 1;
25974	                var r = this.yylloc.range;
25975
25976	                this.yylloc = { first_line: this.yylloc.first_line,
25977	                    last_line: this.yylineno + 1,
25978	                    first_column: this.yylloc.first_column,
25979	                    last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
25980	                };
25981
25982	                if (this.options.ranges) {
25983	                    this.yylloc.range = [r[0], r[0] + this.yyleng - len];
25984	                }
25985	                return this;
25986	            },
25987	            more: function more() {
25988	                this._more = true;
25989	                return this;
25990	            },
25991	            less: function less(n) {
25992	                this.unput(this.match.slice(n));
25993	            },
25994	            pastInput: function pastInput() {
25995	                var past = this.matched.substr(0, this.matched.length - this.match.length);
25996	                return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
25997	            },
25998	            upcomingInput: function upcomingInput() {
25999	                var next = this.match;
26000	                if (next.length < 20) {
26001	                    next += this._input.substr(0, 20 - next.length);
26002	                }
26003	                return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
26004	            },
26005	            showPosition: function showPosition() {
26006	                var pre = this.pastInput();
26007	                var c = new Array(pre.length + 1).join("-");
26008	                return pre + this.upcomingInput() + "\n" + c + "^";
26009	            },
26010	            next: function next() {
26011	                if (this.done) {
26012	                    return this.EOF;
26013	                }
26014	                if (!this._input) this.done = true;
26015
26016	                var token, match, tempMatch, index, col, lines;
26017	                if (!this._more) {
26018	                    this.yytext = '';
26019	                    this.match = '';
26020	                }
26021	                var rules = this._currentRules();
26022	                for (var i = 0; i < rules.length; i++) {
26023	                    tempMatch = this._input.match(this.rules[rules[i]]);
26024	                    if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
26025	                        match = tempMatch;
26026	                        index = i;
26027	                        if (!this.options.flex) break;
26028	                    }
26029	                }
26030	                if (match) {
26031	                    lines = match[0].match(/(?:\r\n?|\n).*/g);
26032	                    if (lines) this.yylineno += lines.length;
26033	                    this.yylloc = { first_line: this.yylloc.last_line,
26034	                        last_line: this.yylineno + 1,
26035	                        first_column: this.yylloc.last_column,
26036	                        last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length };
26037	                    this.yytext += match[0];
26038	                    this.match += match[0];
26039	                    this.matches = match;
26040	                    this.yyleng = this.yytext.length;
26041	                    if (this.options.ranges) {
26042	                        this.yylloc.range = [this.offset, this.offset += this.yyleng];
26043	                    }
26044	                    this._more = false;
26045	                    this._input = this._input.slice(match[0].length);
26046	                    this.matched += match[0];
26047	                    token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
26048	                    if (this.done && this._input) this.done = false;
26049	                    if (token) return token;else return;
26050	                }
26051	                if (this._input === "") {
26052	                    return this.EOF;
26053	                } else {
26054	                    return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno });
26055	                }
26056	            },
26057	            lex: function lex() {
26058	                var r = this.next();
26059	                if (typeof r !== 'undefined') {
26060	                    return r;
26061	                } else {
26062	                    return this.lex();
26063	                }
26064	            },
26065	            begin: function begin(condition) {
26066	                this.conditionStack.push(condition);
26067	            },
26068	            popState: function popState() {
26069	                return this.conditionStack.pop();
26070	            },
26071	            _currentRules: function _currentRules() {
26072	                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
26073	            },
26074	            topState: function topState() {
26075	                return this.conditionStack[this.conditionStack.length - 2];
26076	            },
26077	            pushState: function begin(condition) {
26078	                this.begin(condition);
26079	            } };
26080	        lexer.options = {};
26081	        lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START
vendor: 7,148 bytes, lines 26081-26261
26081
26082	        /*``*/) {
26083
26084	            function strip(start, end) {
26085	                return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end);
26086	            }
26087
26088	            var YYSTATE = YY_START;
26089	            switch ($avoiding_name_collisions) {
26090	                case 0:
26091	                    if (yy_.yytext.slice(-2) === "\\\\") {
26092	                        strip(0, 1);
26093	                        this.begin("mu");
26094	                    } else if (yy_.yytext.slice(-1) === "\\") {
26095	                        strip(0, 1);
26096	                        this.begin("emu");
26097	                    } else {
26098	                        this.begin("mu");
26099	                    }
26100	                    if (yy_.yytext) return 15;
26101
26102	                    break;
26103	                case 1:
26104	                    return 15;
26105	                    break;
26106	                case 2:
26107	                    this.popState();
26108	                    return 15;
26109
26110	                    break;
26111	                case 3:
26112	                    this.begin('raw');return 15;
26113	                    break;
26114	                case 4:
26115	                    this.popState();
26116	                    // Should be using `this.topState()` below, but it currently
26117	                    // returns the second top instead of the first top. Opened an
26118	                    // issue about it at https://github.com/zaach/jison/issues/291
26119	                    if (this.conditionStack[this.conditionStack.length - 1] === 'raw') {
26120	                        return 15;
26121	                    } else {
26122	                        yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9);
26123	                        return 'END_RAW_BLOCK';
26124	                    }
26125
26126	                    break;
26127	                case 5:
26128	                    return 15;
26129	                    break;
26130	                case 6:
26131	                    this.popState();
26132	                    return 14;
26133
26134	                    break;
26135	                case 7:
26136	                    return 65;
26137	                    break;
26138	                case 8:
26139	                    return 68;
26140	                    break;
26141	                case 9:
26142	                    return 19;
26143	                    break;
26144	                case 10:
26145	                    this.popState();
26146	                    this.begin('raw');
26147	                    return 23;
26148
26149	                    break;
26150	                case 11:
26151	                    return 55;
26152	                    break;
26153	                case 12:
26154	                    return 60;
26155	                    break;
26156	                case 13:
26157	                    return 29;
26158	                    break;
26159	                case 14:
26160	                    return 47;
26161	                    break;
26162	                case 15:
26163	                    this.popState();return 44;
26164	                    break;
26165	                case 16:
26166	                    this.popState();return 44;
26167	                    break;
26168	                case 17:
26169	                    return 34;
26170	                    break;
26171	                case 18:
26172	                    return 39;
26173	                    break;
26174	                case 19:
26175	                    return 51;
26176	                    break;
26177	                case 20:
26178	                    return 48;
26179	                    break;
26180	                case 21:
26181	                    this.unput(yy_.yytext);
26182	                    this.popState();
26183	                    this.begin('com');
26184
26185	                    break;
26186	                case 22:
26187	                    this.popState();
26188	                    return 14;
26189
26190	                    break;
26191	                case 23:
26192	                    return 48;
26193	                    break;
26194	                case 24:
26195	                    return 73;
26196	                    break;
26197	                case 25:
26198	                    return 72;
26199	                    break;
26200	                case 26:
26201	                    return 72;
26202	                    break;
26203	                case 27:
26204	                    return 87;
26205	                    break;
26206	                case 28:
26207	                    // ignore whitespace
26208	                    break;
26209	                case 29:
26210	                    this.popState();return 54;
26211	                    break;
26212	                case 30:
26213	                    this.popState();return 33;
26214	                    break;
26215	                case 31:
26216	                    yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80;
26217	                    break;
26218	                case 32:
26219	                    yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80;
26220	                    break;
26221	                case 33:
26222	                    return 85;
26223	                    break;
26224	                case 34:
26225	                    return 82;
26226	                    break;
26227	                case 35:
26228	                    return 82;
26229	                    break;
26230	                case 36:
26231	                    return 83;
26232	                    break;
26233	                case 37:
26234	                    return 84;
26235	                    break;
26236	                case 38:
26237	                    return 81;
26238	                    break;
26239	                case 39:
26240	                    return 75;
26241	                    break;
26242	                case 40:
26243	                    return 77;
26244	                    break;
26245	                case 41:
26246	                    return 72;
26247	                    break;
26248	                case 42:
26249	                    yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72;
26250	                    break;
26251	                case 43:
26252	                    return 'INVALID';
26253	                    break;
26254	                case 44:
26255	                    return 5;
26256	                    break;
26257	            }
26258	        };
26259	        lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/];
26260	        lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } };
26261	        return lexer;
vendor: 12,193 bytes, lines 26262-26686
26262	    })();
26263	    parser.lexer = lexer;
26264	    function Parser() {
26265	        this.yy = {};
26266	    }Parser.prototype = parser;parser.Parser = Parser;
26267	    return new Parser();
26268	})();exports["default"] = handlebars;
26269	module.exports = exports["default"];
26270
26271/***/ }),
26272/* 38 */
26273/***/ (function(module, exports, __webpack_require__) {
26274
26275	'use strict';
26276
26277	var _interopRequireDefault = __webpack_require__(1)['default'];
26278
26279	exports.__esModule = true;
26280
26281	var _visitor = __webpack_require__(39);
26282
26283	var _visitor2 = _interopRequireDefault(_visitor);
26284
26285	function WhitespaceControl() {
26286	  var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
26287
26288	  this.options = options;
26289	}
26290	WhitespaceControl.prototype = new _visitor2['default']();
26291
26292	WhitespaceControl.prototype.Program = function (program) {
26293	  var doStandalone = !this.options.ignoreStandalone;
26294
26295	  var isRoot = !this.isRootSeen;
26296	  this.isRootSeen = true;
26297
26298	  var body = program.body;
26299	  for (var i = 0, l = body.length; i < l; i++) {
26300	    var current = body[i],
26301	        strip = this.accept(current);
26302
26303	    if (!strip) {
26304	      continue;
26305	    }
26306
26307	    var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
26308	        _isNextWhitespace = isNextWhitespace(body, i, isRoot),
26309	        openStandalone = strip.openStandalone && _isPrevWhitespace,
26310	        closeStandalone = strip.closeStandalone && _isNextWhitespace,
26311	        inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
26312
26313	    if (strip.close) {
26314	      omitRight(body, i, true);
26315	    }
26316	    if (strip.open) {
26317	      omitLeft(body, i, true);
26318	    }
26319
26320	    if (doStandalone && inlineStandalone) {
26321	      omitRight(body, i);
26322
26323	      if (omitLeft(body, i)) {
26324	        // If we are on a standalone node, save the indent info for partials
26325	        if (current.type === 'PartialStatement') {
26326	          // Pull out the whitespace from the final line
26327	          current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1];
26328	        }
26329	      }
26330	    }
26331	    if (doStandalone && openStandalone) {
26332	      omitRight((current.program || current.inverse).body);
26333
26334	      // Strip out the previous content node if it's whitespace only
26335	      omitLeft(body, i);
26336	    }
26337	    if (doStandalone && closeStandalone) {
26338	      // Always strip the next node
26339	      omitRight(body, i);
26340
26341	      omitLeft((current.inverse || current.program).body);
26342	    }
26343	  }
26344
26345	  return program;
26346	};
26347
26348	WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) {
26349	  this.accept(block.program);
26350	  this.accept(block.inverse);
26351
26352	  // Find the inverse program that is involed with whitespace stripping.
26353	  var program = block.program || block.inverse,
26354	      inverse = block.program && block.inverse,
26355	      firstInverse = inverse,
26356	      lastInverse = inverse;
26357
26358	  if (inverse && inverse.chained) {
26359	    firstInverse = inverse.body[0].program;
26360
26361	    // Walk the inverse chain to find the last inverse that is actually in the chain.
26362	    while (lastInverse.chained) {
26363	      lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
26364	    }
26365	  }
26366
26367	  var strip = {
26368	    open: block.openStrip.open,
26369	    close: block.closeStrip.close,
26370
26371	    // Determine the standalone candiacy. Basically flag our content as being possibly standalone
26372	    // so our parent can determine if we actually are standalone
26373	    openStandalone: isNextWhitespace(program.body),
26374	    closeStandalone: isPrevWhitespace((firstInverse || program).body)
26375	  };
26376
26377	  if (block.openStrip.close) {
26378	    omitRight(program.body, null, true);
26379	  }
26380
26381	  if (inverse) {
26382	    var inverseStrip = block.inverseStrip;
26383
26384	    if (inverseStrip.open) {
26385	      omitLeft(program.body, null, true);
26386	    }
26387
26388	    if (inverseStrip.close) {
26389	      omitRight(firstInverse.body, null, true);
26390	    }
26391	    if (block.closeStrip.open) {
26392	      omitLeft(lastInverse.body, null, true);
26393	    }
26394
26395	    // Find standalone else statments
26396	    if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) {
26397	      omitLeft(program.body);
26398	      omitRight(firstInverse.body);
26399	    }
26400	  } else if (block.closeStrip.open) {
26401	    omitLeft(program.body, null, true);
26402	  }
26403
26404	  return strip;
26405	};
26406
26407	WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) {
26408	  return mustache.strip;
26409	};
26410
26411	WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) {
26412	  /* istanbul ignore next */
26413	  var strip = node.strip || {};
26414	  return {
26415	    inlineStandalone: true,
26416	    open: strip.open,
26417	    close: strip.close
26418	  };
26419	};
26420
26421	function isPrevWhitespace(body, i, isRoot) {
26422	  if (i === undefined) {
26423	    i = body.length;
26424	  }
26425
26426	  // Nodes that end with newlines are considered whitespace (but are special
26427	  // cased for strip operations)
26428	  var prev = body[i - 1],
26429	      sibling = body[i - 2];
26430	  if (!prev) {
26431	    return isRoot;
26432	  }
26433
26434	  if (prev.type === 'ContentStatement') {
26435	    return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original);
26436	  }
26437	}
26438	function isNextWhitespace(body, i, isRoot) {
26439	  if (i === undefined) {
26440	    i = -1;
26441	  }
26442
26443	  var next = body[i + 1],
26444	      sibling = body[i + 2];
26445	  if (!next) {
26446	    return isRoot;
26447	  }
26448
26449	  if (next.type === 'ContentStatement') {
26450	    return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original);
26451	  }
26452	}
26453
26454	// Marks the node to the right of the position as omitted.
26455	// I.e. {{foo}}' ' will mark the ' ' node as omitted.
26456	//
26457	// If i is undefined, then the first child will be marked as such.
26458	//
26459	// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
26460	// content is met.
26461	function omitRight(body, i, multiple) {
26462	  var current = body[i == null ? 0 : i + 1];
26463	  if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) {
26464	    return;
26465	  }
26466
26467	  var original = current.value;
26468	  current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, '');
26469	  current.rightStripped = current.value !== original;
26470	}
26471
26472	// Marks the node to the left of the position as omitted.
26473	// I.e. ' '{{foo}} will mark the ' ' node as omitted.
26474	//
26475	// If i is undefined then the last child will be marked as such.
26476	//
26477	// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
26478	// content is met.
26479	function omitLeft(body, i, multiple) {
26480	  var current = body[i == null ? body.length - 1 : i - 1];
26481	  if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) {
26482	    return;
26483	  }
26484
26485	  // We omit the last node if it's whitespace only and not preceeded by a non-content node.
26486	  var original = current.value;
26487	  current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, '');
26488	  current.leftStripped = current.value !== original;
26489	  return current.leftStripped;
26490	}
26491
26492	exports['default'] = WhitespaceControl;
26493	module.exports = exports['default'];
26494
26495/***/ }),
26496/* 39 */
26497/***/ (function(module, exports, __webpack_require__) {
26498
26499	'use strict';
26500
26501	var _interopRequireDefault = __webpack_require__(1)['default'];
26502
26503	exports.__esModule = true;
26504
26505	var _exception = __webpack_require__(6);
26506
26507	var _exception2 = _interopRequireDefault(_exception);
26508
26509	function Visitor() {
26510	  this.parents = [];
26511	}
26512
26513	Visitor.prototype = {
26514	  constructor: Visitor,
26515	  mutating: false,
26516
26517	  // Visits a given value. If mutating, will replace the value if necessary.
26518	  acceptKey: function acceptKey(node, name) {
26519	    var value = this.accept(node[name]);
26520	    if (this.mutating) {
26521	      // Hacky sanity check: This may have a few false positives for type for the helper
26522	      // methods but will generally do the right thing without a lot of overhead.
26523	      if (value && !Visitor.prototype[value.type]) {
26524	        throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
26525	      }
26526	      node[name] = value;
26527	    }
26528	  },
26529
26530	  // Performs an accept operation with added sanity check to ensure
26531	  // required keys are not removed.
26532	  acceptRequired: function acceptRequired(node, name) {
26533	    this.acceptKey(node, name);
26534
26535	    if (!node[name]) {
26536	      throw new _exception2['default'](node.type + ' requires ' + name);
26537	    }
26538	  },
26539
26540	  // Traverses a given array. If mutating, empty respnses will be removed
26541	  // for child elements.
26542	  acceptArray: function acceptArray(array) {
26543	    for (var i = 0, l = array.length; i < l; i++) {
26544	      this.acceptKey(array, i);
26545
26546	      if (!array[i]) {
26547	        array.splice(i, 1);
26548	        i--;
26549	        l--;
26550	      }
26551	    }
26552	  },
26553
26554	  accept: function accept(object) {
26555	    if (!object) {
26556	      return;
26557	    }
26558
26559	    /* istanbul ignore next: Sanity code */
26560	    if (!this[object.type]) {
26561	      throw new _exception2['default']('Unknown type: ' + object.type, object);
26562	    }
26563
26564	    if (this.current) {
26565	      this.parents.unshift(this.current);
26566	    }
26567	    this.current = object;
26568
26569	    var ret = this[object.type](object);
26570
26571	    this.current = this.parents.shift();
26572
26573	    if (!this.mutating || ret) {
26574	      return ret;
26575	    } else if (ret !== false) {
26576	      return object;
26577	    }
26578	  },
26579
26580	  Program: function Program(program) {
26581	    this.acceptArray(program.body);
26582	  },
26583
26584	  MustacheStatement: visitSubExpression,
26585	  Decorator: visitSubExpression,
26586
26587	  BlockStatement: visitBlock,
26588	  DecoratorBlock: visitBlock,
26589
26590	  PartialStatement: visitPartial,
26591	  PartialBlockStatement: function PartialBlockStatement(partial) {
26592	    visitPartial.call(this, partial);
26593
26594	    this.acceptKey(partial, 'program');
26595	  },
26596
26597	  ContentStatement: function ContentStatement() /* content */{},
26598	  CommentStatement: function CommentStatement() /* comment */{},
26599
26600	  SubExpression: visitSubExpression,
26601
26602	  PathExpression: function PathExpression() /* path */{},
26603
26604	  StringLiteral: function StringLiteral() /* string */{},
26605	  NumberLiteral: function NumberLiteral() /* number */{},
26606	  BooleanLiteral: function BooleanLiteral() /* bool */{},
26607	  UndefinedLiteral: function UndefinedLiteral() /* literal */{},
26608	  NullLiteral: function NullLiteral() /* literal */{},
26609
26610	  Hash: function Hash(hash) {
26611	    this.acceptArray(hash.pairs);
26612	  },
26613	  HashPair: function HashPair(pair) {
26614	    this.acceptRequired(pair, 'value');
26615	  }
26616	};
26617
26618	function visitSubExpression(mustache) {
26619	  this.acceptRequired(mustache, 'path');
26620	  this.acceptArray(mustache.params);
26621	  this.acceptKey(mustache, 'hash');
26622	}
26623	function visitBlock(block) {
26624	  visitSubExpression.call(this, block);
26625
26626	  this.acceptKey(block, 'program');
26627	  this.acceptKey(block, 'inverse');
26628	}
26629	function visitPartial(partial) {
26630	  this.acceptRequired(partial, 'name');
26631	  this.acceptArray(partial.params);
26632	  this.acceptKey(partial, 'hash');
26633	}
26634
26635	exports['default'] = Visitor;
26636	module.exports = exports['default'];
26637
26638/***/ }),
26639/* 40 */
26640/***/ (function(module, exports, __webpack_require__) {
26641
26642	'use strict';
26643
26644	var _interopRequireDefault = __webpack_require__(1)['default'];
26645
26646	exports.__esModule = true;
26647	exports.SourceLocation = SourceLocation;
26648	exports.id = id;
26649	exports.stripFlags = stripFlags;
26650	exports.stripComment = stripComment;
26651	exports.preparePath = preparePath;
26652	exports.prepareMustache = prepareMustache;
26653	exports.prepareRawBlock = prepareRawBlock;
26654	exports.prepareBlock = prepareBlock;
26655	exports.prepareProgram = prepareProgram;
26656	exports.preparePartialBlock = preparePartialBlock;
26657
26658	var _exception = __webpack_require__(6);
26659
26660	var _exception2 = _interopRequireDefault(_exception);
26661
26662	function validateClose(open, close) {
26663	  close = close.path ? close.path.original : close;
26664
26665	  if (open.path.original !== close) {
26666	    var errorNode = { loc: open.path.loc };
26667
26668	    throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode);
26669	  }
26670	}
26671
26672	function SourceLocation(source, locInfo) {
26673	  this.source = source;
26674	  this.start = {
26675	    line: locInfo.first_line,
26676	    column: locInfo.first_column
26677	  };
26678	  this.end = {
26679	    line: locInfo.last_line,
26680	    column: locInfo.last_column
26681	  };
26682	}
26683
26684	function id(token) {
26685	  if (/^\[.*\]$/.test(token)) {
26686	    return token.substr(1, token.length - 2
vendor: 4,300 bytes, lines 26686-26870
26686);
26687	  } else {
26688	    return token;
26689	  }
26690	}
26691
26692	function stripFlags(open, close) {
26693	  return {
26694	    open: open.charAt(2) === '~',
26695	    close: close.charAt(close.length - 3) === '~'
26696	  };
26697	}
26698
26699	function stripComment(comment) {
26700	  return comment.replace(/^\{\{~?!-?-?/, '').replace(/-?-?~?\}\}$/, '');
26701	}
26702
26703	function preparePath(data, parts, loc) {
26704	  loc = this.locInfo(loc);
26705
26706	  var original = data ? '@' : '',
26707	      dig = [],
26708	      depth = 0;
26709
26710	  for (var i = 0, l = parts.length; i < l; i++) {
26711	    var part = parts[i].part,
26712
26713	    // If we have [] syntax then we do not treat path references as operators,
26714	    // i.e. foo.[this] resolves to approximately context.foo['this']
26715	    isLiteral = parts[i].original !== part;
26716	    original += (parts[i].separator || '') + part;
26717
26718	    if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
26719	      if (dig.length > 0) {
26720	        throw new _exception2['default']('Invalid path: ' + original, { loc: loc });
26721	      } else if (part === '..') {
26722	        depth++;
26723	      }
26724	    } else {
26725	      dig.push(part);
26726	    }
26727	  }
26728
26729	  return {
26730	    type: 'PathExpression',
26731	    data: data,
26732	    depth: depth,
26733	    parts: dig,
26734	    original: original,
26735	    loc: loc
26736	  };
26737	}
26738
26739	function prepareMustache(path, params, hash, open, strip, locInfo) {
26740	  // Must use charAt to support IE pre-10
26741	  var escapeFlag = open.charAt(3) || open.charAt(2),
26742	      escaped = escapeFlag !== '{' && escapeFlag !== '&';
26743
26744	  var decorator = /\*/.test(open);
26745	  return {
26746	    type: decorator ? 'Decorator' : 'MustacheStatement',
26747	    path: path,
26748	    params: params,
26749	    hash: hash,
26750	    escaped: escaped,
26751	    strip: strip,
26752	    loc: this.locInfo(locInfo)
26753	  };
26754	}
26755
26756	function prepareRawBlock(openRawBlock, contents, close, locInfo) {
26757	  validateClose(openRawBlock, close);
26758
26759	  locInfo = this.locInfo(locInfo);
26760	  var program = {
26761	    type: 'Program',
26762	    body: contents,
26763	    strip: {},
26764	    loc: locInfo
26765	  };
26766
26767	  return {
26768	    type: 'BlockStatement',
26769	    path: openRawBlock.path,
26770	    params: openRawBlock.params,
26771	    hash: openRawBlock.hash,
26772	    program: program,
26773	    openStrip: {},
26774	    inverseStrip: {},
26775	    closeStrip: {},
26776	    loc: locInfo
26777	  };
26778	}
26779
26780	function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
26781	  if (close && close.path) {
26782	    validateClose(openBlock, close);
26783	  }
26784
26785	  var decorator = /\*/.test(openBlock.open);
26786
26787	  program.blockParams = openBlock.blockParams;
26788
26789	  var inverse = undefined,
26790	      inverseStrip = undefined;
26791
26792	  if (inverseAndProgram) {
26793	    if (decorator) {
26794	      throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram);
26795	    }
26796
26797	    if (inverseAndProgram.chain) {
26798	      inverseAndProgram.program.body[0].closeStrip = close.strip;
26799	    }
26800
26801	    inverseStrip = inverseAndProgram.strip;
26802	    inverse = inverseAndProgram.program;
26803	  }
26804
26805	  if (inverted) {
26806	    inverted = inverse;
26807	    inverse = program;
26808	    program = inverted;
26809	  }
26810
26811	  return {
26812	    type: decorator ? 'DecoratorBlock' : 'BlockStatement',
26813	    path: openBlock.path,
26814	    params: openBlock.params,
26815	    hash: openBlock.hash,
26816	    program: program,
26817	    inverse: inverse,
26818	    openStrip: openBlock.strip,
26819	    inverseStrip: inverseStrip,
26820	    closeStrip: close && close.strip,
26821	    loc: this.locInfo(locInfo)
26822	  };
26823	}
26824
26825	function prepareProgram(statements, loc) {
26826	  if (!loc && statements.length) {
26827	    var firstLoc = statements[0].loc,
26828	        lastLoc = statements[statements.length - 1].loc;
26829
26830	    /* istanbul ignore else */
26831	    if (firstLoc && lastLoc) {
26832	      loc = {
26833	        source: firstLoc.source,
26834	        start: {
26835	          line: firstLoc.start.line,
26836	          column: firstLoc.start.column
26837	        },
26838	        end: {
26839	          line: lastLoc.end.line,
26840	          column: lastLoc.end.column
26841	        }
26842	      };
26843	    }
26844	  }
26845
26846	  return {
26847	    type: 'Program',
26848	    body: statements,
26849	    strip: {},
26850	    loc: loc
26851	  };
26852	}
26853
26854	function preparePartialBlock(open, program, close, locInfo) {
26855	  validateClose(open, close);
26856
26857	  return {
26858	    type: 'PartialBlockStatement',
26859	    name: open.path,
26860	    params: open.params,
26861	    hash: open.hash,
26862	    program: program,
26863	    openStrip: open.strip,
26864	    closeStrip: close && close.strip,
26865	    loc: this.locInfo(locInfo)
26866	  };
26867	}
26868
26869/***/ }),
26870/* 
vendor: 2,694 bytes, lines 26870-26963
2687041 */
26871/***/ (function(module, exports, __webpack_require__) {
26872
26873	/* eslint-disable new-cap */
26874
26875	'use strict';
26876
26877	var _interopRequireDefault = __webpack_require__(1)['default'];
26878
26879	exports.__esModule = true;
26880	exports.Compiler = Compiler;
26881	exports.precompile = precompile;
26882	exports.compile = compile;
26883
26884	var _exception = __webpack_require__(6);
26885
26886	var _exception2 = _interopRequireDefault(_exception);
26887
26888	var _utils = __webpack_require__(5);
26889
26890	var _ast = __webpack_require__(35);
26891
26892	var _ast2 = _interopRequireDefault(_ast);
26893
26894	var slice = [].slice;
26895
26896	function Compiler() {}
26897
26898	// the foundHelper register will disambiguate helper lookup from finding a
26899	// function in a context. This is necessary for mustache compatibility, which
26900	// requires that context functions in blocks are evaluated by blockHelperMissing,
26901	// and then proceed as if the resulting value was provided to blockHelperMissing.
26902
26903	Compiler.prototype = {
26904	  compiler: Compiler,
26905
26906	  equals: function equals(other) {
26907	    var len = this.opcodes.length;
26908	    if (other.opcodes.length !== len) {
26909	      return false;
26910	    }
26911
26912	    for (var i = 0; i < len; i++) {
26913	      var opcode = this.opcodes[i],
26914	          otherOpcode = other.opcodes[i];
26915	      if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
26916	        return false;
26917	      }
26918	    }
26919
26920	    // We know that length is the same between the two arrays because they are directly tied
26921	    // to the opcode behavior above.
26922	    len = this.children.length;
26923	    for (var i = 0; i < len; i++) {
26924	      if (!this.children[i].equals(other.children[i])) {
26925	        return false;
26926	      }
26927	    }
26928
26929	    return true;
26930	  },
26931
26932	  guid: 0,
26933
26934	  compile: function compile(program, options) {
26935	    this.sourceNode = [];
26936	    this.opcodes = [];
26937	    this.children = [];
26938	    this.options = options;
26939	    this.stringParams = options.stringParams;
26940	    this.trackIds = options.trackIds;
26941
26942	    options.blockParams = options.blockParams || [];
26943
26944	    // These changes will propagate to the other compiler components
26945	    var knownHelpers = options.knownHelpers;
26946	    options.knownHelpers = {
26947	      'helperMissing': true,
26948	      'blockHelperMissing': true,
26949	      'each': true,
26950	      'if': true,
26951	      'unless': true,
26952	      'with': true,
26953	      'log': true,
26954	      'lookup': true
26955	    };
26956	    if (knownHelpers) {
26957	      // the next line should use "Object.keys", but the code has been like this a long time and changing it, might
26958	      // cause backwards-compatibility issues... It's an old library...
26959	      // eslint-disable-next-line guard-for-in
26960	      for (var _name in knownHelpers) {
26961	        this.options.knownHelpers[_name] = knownHelpers[_name];
26962	      }
26963	    }
vendor: 7,760 bytes, lines 26963-27229
26963
26964
26965	    return this.accept(program);
26966	  },
26967
26968	  compileProgram: function compileProgram(program) {
26969	    var childCompiler = new this.compiler(),
26970	        // eslint-disable-line new-cap
26971	    result = childCompiler.compile(program, this.options),
26972	        guid = this.guid++;
26973
26974	    this.usePartial = this.usePartial || result.usePartial;
26975
26976	    this.children[guid] = result;
26977	    this.useDepths = this.useDepths || result.useDepths;
26978
26979	    return guid;
26980	  },
26981
26982	  accept: function accept(node) {
26983	    /* istanbul ignore next: Sanity code */
26984	    if (!this[node.type]) {
26985	      throw new _exception2['default']('Unknown type: ' + node.type, node);
26986	    }
26987
26988	    this.sourceNode.unshift(node);
26989	    var ret = this[node.type](node);
26990	    this.sourceNode.shift();
26991	    return ret;
26992	  },
26993
26994	  Program: function Program(program) {
26995	    this.options.blockParams.unshift(program.blockParams);
26996
26997	    var body = program.body,
26998	        bodyLength = body.length;
26999	    for (var i = 0; i < bodyLength; i++) {
27000	      this.accept(body[i]);
27001	    }
27002
27003	    this.options.blockParams.shift();
27004
27005	    this.isSimple = bodyLength === 1;
27006	    this.blockParams = program.blockParams ? program.blockParams.length : 0;
27007
27008	    return this;
27009	  },
27010
27011	  BlockStatement: function BlockStatement(block) {
27012	    transformLiteralToPath(block);
27013
27014	    var program = block.program,
27015	        inverse = block.inverse;
27016
27017	    program = program && this.compileProgram(program);
27018	    inverse = inverse && this.compileProgram(inverse);
27019
27020	    var type = this.classifySexpr(block);
27021
27022	    if (type === 'helper') {
27023	      this.helperSexpr(block, program, inverse);
27024	    } else if (type === 'simple') {
27025	      this.simpleSexpr(block);
27026
27027	      // now that the simple mustache is resolved, we need to
27028	      // evaluate it by executing `blockHelperMissing`
27029	      this.opcode('pushProgram', program);
27030	      this.opcode('pushProgram', inverse);
27031	      this.opcode('emptyHash');
27032	      this.opcode('blockValue', block.path.original);
27033	    } else {
27034	      this.ambiguousSexpr(block, program, inverse);
27035
27036	      // now that the simple mustache is resolved, we need to
27037	      // evaluate it by executing `blockHelperMissing`
27038	      this.opcode('pushProgram', program);
27039	      this.opcode('pushProgram', inverse);
27040	      this.opcode('emptyHash');
27041	      this.opcode('ambiguousBlockValue');
27042	    }
27043
27044	    this.opcode('append');
27045	  },
27046
27047	  DecoratorBlock: function DecoratorBlock(decorator) {
27048	    var program = decorator.program && this.compileProgram(decorator.program);
27049	    var params = this.setupFullMustacheParams(decorator, program, undefined),
27050	        path = decorator.path;
27051
27052	    this.useDecorators = true;
27053	    this.opcode('registerDecorator', params.length, path.original);
27054	  },
27055
27056	  PartialStatement: function PartialStatement(partial) {
27057	    this.usePartial = true;
27058
27059	    var program = partial.program;
27060	    if (program) {
27061	      program = this.compileProgram(partial.program);
27062	    }
27063
27064	    var params = partial.params;
27065	    if (params.length > 1) {
27066	      throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial);
27067	    } else if (!params.length) {
27068	      if (this.options.explicitPartialContext) {
27069	        this.opcode('pushLiteral', 'undefined');
27070	      } else {
27071	        params.push({ type: 'PathExpression', parts: [], depth: 0 });
27072	      }
27073	    }
27074
27075	    var partialName = partial.name.original,
27076	        isDynamic = partial.name.type === 'SubExpression';
27077	    if (isDynamic) {
27078	      this.accept(partial.name);
27079	    }
27080
27081	    this.setupFullMustacheParams(partial, program, undefined, true);
27082
27083	    var indent = partial.indent || '';
27084	    if (this.options.preventIndent && indent) {
27085	      this.opcode('appendContent', indent);
27086	      indent = '';
27087	    }
27088
27089	    this.opcode('invokePartial', isDynamic, partialName, indent);
27090	    this.opcode('append');
27091	  },
27092	  PartialBlockStatement: function PartialBlockStatement(partialBlock) {
27093	    this.PartialStatement(partialBlock);
27094	  },
27095
27096	  MustacheStatement: function MustacheStatement(mustache) {
27097	    this.SubExpression(mustache);
27098
27099	    if (mustache.escaped && !this.options.noEscape) {
27100	      this.opcode('appendEscaped');
27101	    } else {
27102	      this.opcode('append');
27103	    }
27104	  },
27105	  Decorator: function Decorator(decorator) {
27106	    this.DecoratorBlock(decorator);
27107	  },
27108
27109	  ContentStatement: function ContentStatement(content) {
27110	    if (content.value) {
27111	      this.opcode('appendContent', content.value);
27112	    }
27113	  },
27114
27115	  CommentStatement: function CommentStatement() {},
27116
27117	  SubExpression: function SubExpression(sexpr) {
27118	    transformLiteralToPath(sexpr);
27119	    var type = this.classifySexpr(sexpr);
27120
27121	    if (type === 'simple') {
27122	      this.simpleSexpr(sexpr);
27123	    } else if (type === 'helper') {
27124	      this.helperSexpr(sexpr);
27125	    } else {
27126	      this.ambiguousSexpr(sexpr);
27127	    }
27128	  },
27129	  ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
27130	    var path = sexpr.path,
27131	        name = path.parts[0],
27132	        isBlock = program != null || inverse != null;
27133
27134	    this.opcode('getContext', path.depth);
27135
27136	    this.opcode('pushProgram', program);
27137	    this.opcode('pushProgram', inverse);
27138
27139	    path.strict = true;
27140	    this.accept(path);
27141
27142	    this.opcode('invokeAmbiguous', name, isBlock);
27143	  },
27144
27145	  simpleSexpr: function simpleSexpr(sexpr) {
27146	    var path = sexpr.path;
27147	    path.strict = true;
27148	    this.accept(path);
27149	    this.opcode('resolvePossibleLambda');
27150	  },
27151
27152	  helperSexpr: function helperSexpr(sexpr, program, inverse) {
27153	    var params = this.setupFullMustacheParams(sexpr, program, inverse),
27154	        path = sexpr.path,
27155	        name = path.parts[0];
27156
27157	    if (this.options.knownHelpers[name]) {
27158	      this.opcode('invokeKnownHelper', params.length, name);
27159	    } else if (this.options.knownHelpersOnly) {
27160	      throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
27161	    } else {
27162	      path.strict = true;
27163	      path.falsy = true;
27164
27165	      this.accept(path);
27166	      this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path));
27167	    }
27168	  },
27169
27170	  PathExpression: function PathExpression(path) {
27171	    this.addDepth(path.depth);
27172	    this.opcode('getContext', path.depth);
27173
27174	    var name = path.parts[0],
27175	        scoped = _ast2['default'].helpers.scopedId(path),
27176	        blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
27177
27178	    if (blockParamId) {
27179	      this.opcode('lookupBlockParam', blockParamId, path.parts);
27180	    } else if (!name) {
27181	      // Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
27182	      this.opcode('pushContext');
27183	    } else if (path.data) {
27184	      this.options.data = true;
27185	      this.opcode('lookupData', path.depth, path.parts, path.strict);
27186	    } else {
27187	      this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
27188	    }
27189	  },
27190
27191	  StringLiteral: function StringLiteral(string) {
27192	    this.opcode('pushString', string.value);
27193	  },
27194
27195	  NumberLiteral: function NumberLiteral(number) {
27196	    this.opcode('pushLiteral', number.value);
27197	  },
27198
27199	  BooleanLiteral: function BooleanLiteral(bool) {
27200	    this.opcode('pushLiteral', bool.value);
27201	  },
27202
27203	  UndefinedLiteral: function UndefinedLiteral() {
27204	    this.opcode('pushLiteral', 'undefined');
27205	  },
27206
27207	  NullLiteral: function NullLiteral() {
27208	    this.opcode('pushLiteral', 'null');
27209	  },
27210
27211	  Hash: function Hash(hash) {
27212	    var pairs = hash.pairs,
27213	        i = 0,
27214	        l = pairs.length;
27215
27216	    this.opcode('pushHash');
27217
27218	    for (; i < l; i++) {
27219	      this.pushParam(pairs[i].value);
27220	    }
27221	    while (i--) {
27222	      this.opcode('assignToHash', pairs[i].key);
27223	    }
27224	    this.opcode('popHash');
27225	  },
27226
27227	  // HELPERS
27228	  opcode: function opcode(name) {
27229	    this.opcodes.push({
vendor: 5,637 bytes, lines 27229-27414
27229 opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
27230	  },
27231
27232	  addDepth: function addDepth(depth) {
27233	    if (!depth) {
27234	      return;
27235	    }
27236
27237	    this.useDepths = true;
27238	  },
27239
27240	  classifySexpr: function classifySexpr(sexpr) {
27241	    var isSimple = _ast2['default'].helpers.simpleId(sexpr.path);
27242
27243	    var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
27244
27245	    // a mustache is an eligible helper if:
27246	    // * its id is simple (a single part, not `this` or `..`)
27247	    var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr);
27248
27249	    // if a mustache is an eligible helper but not a definite
27250	    // helper, it is ambiguous, and will be resolved in a later
27251	    // pass or at runtime.
27252	    var isEligible = !isBlockParam && (isHelper || isSimple);
27253
27254	    // if ambiguous, we can possibly resolve the ambiguity now
27255	    // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
27256	    if (isEligible && !isHelper) {
27257	      var _name2 = sexpr.path.parts[0],
27258	          options = this.options;
27259
27260	      if (options.knownHelpers[_name2]) {
27261	        isHelper = true;
27262	      } else if (options.knownHelpersOnly) {
27263	        isEligible = false;
27264	      }
27265	    }
27266
27267	    if (isHelper) {
27268	      return 'helper';
27269	    } else if (isEligible) {
27270	      return 'ambiguous';
27271	    } else {
27272	      return 'simple';
27273	    }
27274	  },
27275
27276	  pushParams: function pushParams(params) {
27277	    for (var i = 0, l = params.length; i < l; i++) {
27278	      this.pushParam(params[i]);
27279	    }
27280	  },
27281
27282	  pushParam: function pushParam(val) {
27283	    var value = val.value != null ? val.value : val.original || '';
27284
27285	    if (this.stringParams) {
27286	      if (value.replace) {
27287	        value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.');
27288	      }
27289
27290	      if (val.depth) {
27291	        this.addDepth(val.depth);
27292	      }
27293	      this.opcode('getContext', val.depth || 0);
27294	      this.opcode('pushStringParam', value, val.type);
27295
27296	      if (val.type === 'SubExpression') {
27297	        // SubExpressions get evaluated and passed in
27298	        // in string params mode.
27299	        this.accept(val);
27300	      }
27301	    } else {
27302	      if (this.trackIds) {
27303	        var blockParamIndex = undefined;
27304	        if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) {
27305	          blockParamIndex = this.blockParamIndex(val.parts[0]);
27306	        }
27307	        if (blockParamIndex) {
27308	          var blockParamChild = val.parts.slice(1).join('.');
27309	          this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
27310	        } else {
27311	          value = val.original || value;
27312	          if (value.replace) {
27313	            value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, '');
27314	          }
27315
27316	          this.opcode('pushId', val.type, value);
27317	        }
27318	      }
27319	      this.accept(val);
27320	    }
27321	  },
27322
27323	  setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) {
27324	    var params = sexpr.params;
27325	    this.pushParams(params);
27326
27327	    this.opcode('pushProgram', program);
27328	    this.opcode('pushProgram', inverse);
27329
27330	    if (sexpr.hash) {
27331	      this.accept(sexpr.hash);
27332	    } else {
27333	      this.opcode('emptyHash', omitEmpty);
27334	    }
27335
27336	    return params;
27337	  },
27338
27339	  blockParamIndex: function blockParamIndex(name) {
27340	    for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
27341	      var blockParams = this.options.blockParams[depth],
27342	          param = blockParams && _utils.indexOf(blockParams, name);
27343	      if (blockParams && param >= 0) {
27344	        return [depth, param];
27345	      }
27346	    }
27347	  }
27348	};
27349
27350	function precompile(input, options, env) {
27351	  if (input == null || typeof input !== 'string' && input.type !== 'Program') {
27352	    throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
27353	  }
27354
27355	  options = options || {};
27356	  if (!('data' in options)) {
27357	    options.data = true;
27358	  }
27359	  if (options.compat) {
27360	    options.useDepths = true;
27361	  }
27362
27363	  var ast = env.parse(input, options),
27364	      environment = new env.Compiler().compile(ast, options);
27365	  return new env.JavaScriptCompiler().compile(environment, options);
27366	}
27367
27368	function compile(input, options, env) {
27369	  if (options === undefined) options = {};
27370
27371	  if (input == null || typeof input !== 'string' && input.type !== 'Program') {
27372	    throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
27373	  }
27374
27375	  options = _utils.extend({}, options);
27376	  if (!('data' in options)) {
27377	    options.data = true;
27378	  }
27379	  if (options.compat) {
27380	    options.useDepths = true;
27381	  }
27382
27383	  var compiled = undefined;
27384
27385	  function compileInput() {
27386	    var ast = env.parse(input, options),
27387	        environment = new env.Compiler().compile(ast, options),
27388	        templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
27389	    return env.template(templateSpec);
27390	  }
27391
27392	  // Template is only compiled on first use and cached after that point.
27393	  function ret(context, execOptions) {
27394	    if (!compiled) {
27395	      compiled = compileInput();
27396	    }
27397	    return compiled.call(this, context, execOptions);
27398	  }
27399	  ret._setup = function (setupOptions) {
27400	    if (!compiled) {
27401	      compiled = compileInput();
27402	    }
27403	    return compiled._setup(setupOptions);
27404	  };
27405	  ret._child = function (i, data, blockParams, depths) {
27406	    if (!compiled) {
27407	      compiled = compileInput();
27408	    }
27409	    return compiled._child(i, data, blockParams, depths);
27410	  };
27411	  return ret;
27412	}
27413
27414	function argEquals(a, b) {
vendor: 8,012 bytes, lines 27415-27681
27415	  if (a === b) {
27416	    return true;
27417	  }
27418
27419	  if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) {
27420	    for (var i = 0; i < a.length; i++) {
27421	      if (!argEquals(a[i], b[i])) {
27422	        return false;
27423	      }
27424	    }
27425	    return true;
27426	  }
27427	}
27428
27429	function transformLiteralToPath(sexpr) {
27430	  if (!sexpr.path.parts) {
27431	    var literal = sexpr.path;
27432	    // Casting to string here to make false and 0 literal values play nicely with the rest
27433	    // of the system.
27434	    sexpr.path = {
27435	      type: 'PathExpression',
27436	      data: false,
27437	      depth: 0,
27438	      parts: [literal.original + ''],
27439	      original: literal.original + '',
27440	      loc: literal.loc
27441	    };
27442	  }
27443	}
27444
27445/***/ }),
27446/* 42 */
27447/***/ (function(module, exports, __webpack_require__) {
27448
27449	'use strict';
27450
27451	var _interopRequireDefault = __webpack_require__(1)['default'];
27452
27453	exports.__esModule = true;
27454
27455	var _base = __webpack_require__(4);
27456
27457	var _exception = __webpack_require__(6);
27458
27459	var _exception2 = _interopRequireDefault(_exception);
27460
27461	var _utils = __webpack_require__(5);
27462
27463	var _codeGen = __webpack_require__(43);
27464
27465	var _codeGen2 = _interopRequireDefault(_codeGen);
27466
27467	function Literal(value) {
27468	  this.value = value;
27469	}
27470
27471	function JavaScriptCompiler() {}
27472
27473	JavaScriptCompiler.prototype = {
27474	  // PUBLIC API: You can override these methods in a subclass to provide
27475	  // alternative compiled forms for name lookup and buffering semantics
27476	  nameLookup: function nameLookup(parent, name /* , type*/) {
27477	    if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
27478	      return [parent, '.', name];
27479	    } else {
27480	      return [parent, '[', JSON.stringify(name), ']'];
27481	    }
27482	  },
27483	  depthedLookup: function depthedLookup(name) {
27484	    return [this.aliasable('container.lookup'), '(depths, "', name, '")'];
27485	  },
27486
27487	  compilerInfo: function compilerInfo() {
27488	    var revision = _base.COMPILER_REVISION,
27489	        versions = _base.REVISION_CHANGES[revision];
27490	    return [revision, versions];
27491	  },
27492
27493	  appendToBuffer: function appendToBuffer(source, location, explicit) {
27494	    // Force a source as this simplifies the merge logic.
27495	    if (!_utils.isArray(source)) {
27496	      source = [source];
27497	    }
27498	    source = this.source.wrap(source, location);
27499
27500	    if (this.environment.isSimple) {
27501	      return ['return ', source, ';'];
27502	    } else if (explicit) {
27503	      // This is a case where the buffer operation occurs as a child of another
27504	      // construct, generally braces. We have to explicitly output these buffer
27505	      // operations to ensure that the emitted code goes in the correct location.
27506	      return ['buffer += ', source, ';'];
27507	    } else {
27508	      source.appendToBuffer = true;
27509	      return source;
27510	    }
27511	  },
27512
27513	  initializeBuffer: function initializeBuffer() {
27514	    return this.quotedString('');
27515	  },
27516	  // END PUBLIC API
27517
27518	  compile: function compile(environment, options, context, asObject) {
27519	    this.environment = environment;
27520	    this.options = options;
27521	    this.stringParams = this.options.stringParams;
27522	    this.trackIds = this.options.trackIds;
27523	    this.precompile = !asObject;
27524
27525	    this.name = this.environment.name;
27526	    this.isChild = !!context;
27527	    this.context = context || {
27528	      decorators: [],
27529	      programs: [],
27530	      environments: []
27531	    };
27532
27533	    this.preamble();
27534
27535	    this.stackSlot = 0;
27536	    this.stackVars = [];
27537	    this.aliases = {};
27538	    this.registers = { list: [] };
27539	    this.hashes = [];
27540	    this.compileStack = [];
27541	    this.inlineStack = [];
27542	    this.blockParams = [];
27543
27544	    this.compileChildren(environment, options);
27545
27546	    this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat;
27547	    this.useBlockParams = this.useBlockParams || environment.useBlockParams;
27548
27549	    var opcodes = environment.opcodes,
27550	        opcode = undefined,
27551	        firstLoc = undefined,
27552	        i = undefined,
27553	        l = undefined;
27554
27555	    for (i = 0, l = opcodes.length; i < l; i++) {
27556	      opcode = opcodes[i];
27557
27558	      this.source.currentLocation = opcode.loc;
27559	      firstLoc = firstLoc || opcode.loc;
27560	      this[opcode.opcode].apply(this, opcode.args);
27561	    }
27562
27563	    // Flush any trailing content that might be pending.
27564	    this.source.currentLocation = firstLoc;
27565	    this.pushSource('');
27566
27567	    /* istanbul ignore next */
27568	    if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
27569	      throw new _exception2['default']('Compile completed with content left on stack');
27570	    }
27571
27572	    if (!this.decorators.isEmpty()) {
27573	      this.useDecorators = true;
27574
27575	      this.decorators.prepend('var decorators = container.decorators;\n');
27576	      this.decorators.push('return fn;');
27577
27578	      if (asObject) {
27579	        this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]);
27580	      } else {
27581	        this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n');
27582	        this.decorators.push('}\n');
27583	        this.decorators = this.decorators.merge();
27584	      }
27585	    } else {
27586	      this.decorators = undefined;
27587	    }
27588
27589	    var fn = this.createFunctionContext(asObject);
27590	    if (!this.isChild) {
27591	      var ret = {
27592	        compiler: this.compilerInfo(),
27593	        main: fn
27594	      };
27595
27596	      if (this.decorators) {
27597	        ret.main_d = this.decorators; // eslint-disable-line camelcase
27598	        ret.useDecorators = true;
27599	      }
27600
27601	      var _context = this.context;
27602	      var programs = _context.programs;
27603	      var decorators = _context.decorators;
27604
27605	      for (i = 0, l = programs.length; i < l; i++) {
27606	        if (programs[i]) {
27607	          ret[i] = programs[i];
27608	          if (decorators[i]) {
27609	            ret[i + '_d'] = decorators[i];
27610	            ret.useDecorators = true;
27611	          }
27612	        }
27613	      }
27614
27615	      if (this.environment.usePartial) {
27616	        ret.usePartial = true;
27617	      }
27618	      if (this.options.data) {
27619	        ret.useData = true;
27620	      }
27621	      if (this.useDepths) {
27622	        ret.useDepths = true;
27623	      }
27624	      if (this.useBlockParams) {
27625	        ret.useBlockParams = true;
27626	      }
27627	      if (this.options.compat) {
27628	        ret.compat = true;
27629	      }
27630
27631	      if (!asObject) {
27632	        ret.compiler = JSON.stringify(ret.compiler);
27633
27634	        this.source.currentLocation = { start: { line: 1, column: 0 } };
27635	        ret = this.objectLiteral(ret);
27636
27637	        if (options.srcName) {
27638	          ret = ret.toStringWithSourceMap({ file: options.destName });
27639	          ret.map = ret.map && ret.map.toString();
27640	        } else {
27641	          ret = ret.toString();
27642	        }
27643	      } else {
27644	        ret.compilerOptions = this.options;
27645	      }
27646
27647	      return ret;
27648	    } else {
27649	      return fn;
27650	    }
27651	  },
27652
27653	  preamble: function preamble() {
27654	    // track the last context pushed into place to allow skipping the
27655	    // getContext opcode when it would be a noop
27656	    this.lastContext = 0;
27657	    this.source = new _codeGen2['default'](this.options.srcName);
27658	    this.decorators = new _codeGen2['default'](this.options.srcName);
27659	  },
27660
27661	  createFunctionContext: function createFunctionContext(asObject) {
27662	    var varDeclarations = '';
27663
27664	    var locals = this.stackVars.concat(this.registers.list);
27665	    if (locals.length > 0) {
27666	      varDeclarations += ', ' + locals.join(', ');
27667	    }
27668
27669	    // Generate minimizer alias mappings
27670	    //
27671	    // When using true SourceNodes, this will update all references to the given alias
27672	    // as the source nodes are reused in situ. For the non-source node compilation mode,
27673	    // aliases will not be used, but this case is already being run on the client and
27674	    // we aren't concern about minimizing the template size.
27675	    var aliasCount = 0;
27676	    for (var alias in this.aliases) {
27677	      // eslint-disable-line guard-for-in
27678	      var node = this.aliases[alias];
27679
27680	      if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
27681	        varDeclarations += ', alias' + ++aliasCount + '=' + alias;
vendor: 4,556 bytes, lines 27682-27831
27682	        node.children[0] = 'alias' + aliasCount;
27683	      }
27684	    }
27685
27686	    var params = ['container', 'depth0', 'helpers', 'partials', 'data'];
27687
27688	    if (this.useBlockParams || this.useDepths) {
27689	      params.push('blockParams');
27690	    }
27691	    if (this.useDepths) {
27692	      params.push('depths');
27693	    }
27694
27695	    // Perform a second pass over the output to merge content when possible
27696	    var source = this.mergeSource(varDeclarations);
27697
27698	    if (asObject) {
27699	      params.push(source);
27700
27701	      return Function.apply(this, params);
27702	    } else {
27703	      return this.source.wrap(['function(', params.join(','), ') {\n  ', source, '}']);
27704	    }
27705	  },
27706	  mergeSource: function mergeSource(varDeclarations) {
27707	    var isSimple = this.environment.isSimple,
27708	        appendOnly = !this.forceBuffer,
27709	        appendFirst = undefined,
27710	        sourceSeen = undefined,
27711	        bufferStart = undefined,
27712	        bufferEnd = undefined;
27713	    this.source.each(function (line) {
27714	      if (line.appendToBuffer) {
27715	        if (bufferStart) {
27716	          line.prepend('  + ');
27717	        } else {
27718	          bufferStart = line;
27719	        }
27720	        bufferEnd = line;
27721	      } else {
27722	        if (bufferStart) {
27723	          if (!sourceSeen) {
27724	            appendFirst = true;
27725	          } else {
27726	            bufferStart.prepend('buffer += ');
27727	          }
27728	          bufferEnd.add(';');
27729	          bufferStart = bufferEnd = undefined;
27730	        }
27731
27732	        sourceSeen = true;
27733	        if (!isSimple) {
27734	          appendOnly = false;
27735	        }
27736	      }
27737	    });
27738
27739	    if (appendOnly) {
27740	      if (bufferStart) {
27741	        bufferStart.prepend('return ');
27742	        bufferEnd.add(';');
27743	      } else if (!sourceSeen) {
27744	        this.source.push('return "";');
27745	      }
27746	    } else {
27747	      varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer());
27748
27749	      if (bufferStart) {
27750	        bufferStart.prepend('return buffer + ');
27751	        bufferEnd.add(';');
27752	      } else {
27753	        this.source.push('return buffer;');
27754	      }
27755	    }
27756
27757	    if (varDeclarations) {
27758	      this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
27759	    }
27760
27761	    return this.source.merge();
27762	  },
27763
27764	  // [blockValue]
27765	  //
27766	  // On stack, before: hash, inverse, program, value
27767	  // On stack, after: return value of blockHelperMissing
27768	  //
27769	  // The purpose of this opcode is to take a block of the form
27770	  // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
27771	  // replace it on the stack with the result of properly
27772	  // invoking blockHelperMissing.
27773	  blockValue: function blockValue(name) {
27774	    var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
27775	        params = [this.contextName(0)];
27776	    this.setupHelperArgs(name, 0, params);
27777
27778	    var blockName = this.popStack();
27779	    params.splice(1, 0, blockName);
27780
27781	    this.push(this.source.functionCall(blockHelperMissing, 'call', params));
27782	  },
27783
27784	  // [ambiguousBlockValue]
27785	  //
27786	  // On stack, before: hash, inverse, program, value
27787	  // Compiler value, before: lastHelper=value of last found helper, if any
27788	  // On stack, after, if no lastHelper: same as [blockValue]
27789	  // On stack, after, if lastHelper: value
27790	  ambiguousBlockValue: function ambiguousBlockValue() {
27791	    // We're being a bit cheeky and reusing the options value from the prior exec
27792	    var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
27793	        params = [this.contextName(0)];
27794	    this.setupHelperArgs('', 0, params, true);
27795
27796	    this.flushInline();
27797
27798	    var current = this.topStack();
27799	    params.splice(1, 0, current);
27800
27801	    this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']);
27802	  },
27803
27804	  // [appendContent]
27805	  //
27806	  // On stack, before: ...
27807	  // On stack, after: ...
27808	  //
27809	  // Appends the string value of `content` to the current buffer
27810	  appendContent: function appendContent(content) {
27811	    if (this.pendingContent) {
27812	      content = this.pendingContent + content;
27813	    } else {
27814	      this.pendingLocation = this.source.currentLocation;
27815	    }
27816
27817	    this.pendingContent = content;
27818	  },
27819
27820	  // [append]
27821	  //
27822	  // On stack, before: value, ...
27823	  // On stack, after: ...
27824	  //
27825	  // Coerces `value` to a String and appends it to the current buffer.
27826	  //
27827	  // If `value` is truthy, or 0, it is coerced into a string and appended
27828	  // Otherwise, the empty string is appended
27829	  append: function append() {
27830	    if (this.isInline()) {
27831	      this.replaceStack(function (current) {
vendor: 5,813 bytes, lines 27832-28024
27832	        return [' != null ? ', current, ' : ""'];
27833	      });
27834
27835	      this.pushSource(this.appendToBuffer(this.popStack()));
27836	    } else {
27837	      var local = this.popStack();
27838	      this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
27839	      if (this.environment.isSimple) {
27840	        this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
27841	      }
27842	    }
27843	  },
27844
27845	  // [appendEscaped]
27846	  //
27847	  // On stack, before: value, ...
27848	  // On stack, after: ...
27849	  //
27850	  // Escape `value` and append it to the buffer
27851	  appendEscaped: function appendEscaped() {
27852	    this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')']));
27853	  },
27854
27855	  // [getContext]
27856	  //
27857	  // On stack, before: ...
27858	  // On stack, after: ...
27859	  // Compiler value, after: lastContext=depth
27860	  //
27861	  // Set the value of the `lastContext` compiler value to the depth
27862	  getContext: function getContext(depth) {
27863	    this.lastContext = depth;
27864	  },
27865
27866	  // [pushContext]
27867	  //
27868	  // On stack, before: ...
27869	  // On stack, after: currentContext, ...
27870	  //
27871	  // Pushes the value of the current context onto the stack.
27872	  pushContext: function pushContext() {
27873	    this.pushStackLiteral(this.contextName(this.lastContext));
27874	  },
27875
27876	  // [lookupOnContext]
27877	  //
27878	  // On stack, before: ...
27879	  // On stack, after: currentContext[name], ...
27880	  //
27881	  // Looks up the value of `name` on the current context and pushes
27882	  // it onto the stack.
27883	  lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) {
27884	    var i = 0;
27885
27886	    if (!scoped && this.options.compat && !this.lastContext) {
27887	      // The depthed query is expected to handle the undefined logic for the root level that
27888	      // is implemented below, so we evaluate that directly in compat mode
27889	      this.push(this.depthedLookup(parts[i++]));
27890	    } else {
27891	      this.pushContext();
27892	    }
27893
27894	    this.resolvePath('context', parts, i, falsy, strict);
27895	  },
27896
27897	  // [lookupBlockParam]
27898	  //
27899	  // On stack, before: ...
27900	  // On stack, after: blockParam[name], ...
27901	  //
27902	  // Looks up the value of `parts` on the given block param and pushes
27903	  // it onto the stack.
27904	  lookupBlockParam: function lookupBlockParam(blockParamId, parts) {
27905	    this.useBlockParams = true;
27906
27907	    this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
27908	    this.resolvePath('context', parts, 1);
27909	  },
27910
27911	  // [lookupData]
27912	  //
27913	  // On stack, before: ...
27914	  // On stack, after: data, ...
27915	  //
27916	  // Push the data lookup operator
27917	  lookupData: function lookupData(depth, parts, strict) {
27918	    if (!depth) {
27919	      this.pushStackLiteral('data');
27920	    } else {
27921	      this.pushStackLiteral('container.data(data, ' + depth + ')');
27922	    }
27923
27924	    this.resolvePath('data', parts, 0, true, strict);
27925	  },
27926
27927	  resolvePath: function resolvePath(type, parts, i, falsy, strict) {
27928	    // istanbul ignore next
27929
27930	    var _this = this;
27931
27932	    if (this.options.strict || this.options.assumeObjects) {
27933	      this.push(strictLookup(this.options.strict && strict, this, parts, type));
27934	      return;
27935	    }
27936
27937	    var len = parts.length;
27938	    for (; i < len; i++) {
27939	      /* eslint-disable no-loop-func */
27940	      this.replaceStack(function (current) {
27941	        var lookup = _this.nameLookup(current, parts[i], type);
27942	        // We want to ensure that zero and false are handled properly if the context (falsy flag)
27943	        // needs to have the special handling for these values.
27944	        if (!falsy) {
27945	          return [' != null ? ', lookup, ' : ', current];
27946	        } else {
27947	          // Otherwise we can use generic falsy handling
27948	          return [' && ', lookup];
27949	        }
27950	      });
27951	      /* eslint-enable no-loop-func */
27952	    }
27953	  },
27954
27955	  // [resolvePossibleLambda]
27956	  //
27957	  // On stack, before: value, ...
27958	  // On stack, after: resolved value, ...
27959	  //
27960	  // If the `value` is a lambda, replace it on the stack by
27961	  // the return value of the lambda
27962	  resolvePossibleLambda: function resolvePossibleLambda() {
27963	    this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
27964	  },
27965
27966	  // [pushStringParam]
27967	  //
27968	  // On stack, before: ...
27969	  // On stack, after: string, currentContext, ...
27970	  //
27971	  // This opcode is designed for use in string mode, which
27972	  // provides the string value of a parameter along with its
27973	  // depth rather than resolving it immediately.
27974	  pushStringParam: function pushStringParam(string, type) {
27975	    this.pushContext();
27976	    this.pushString(type);
27977
27978	    // If it's a subexpression, the string result
27979	    // will be pushed after this opcode.
27980	    if (type !== 'SubExpression') {
27981	      if (typeof string === 'string') {
27982	        this.pushString(string);
27983	      } else {
27984	        this.pushStackLiteral(string);
27985	      }
27986	    }
27987	  },
27988
27989	  emptyHash: function emptyHash(omitEmpty) {
27990	    if (this.trackIds) {
27991	      this.push('{}'); // hashIds
27992	    }
27993	    if (this.stringParams) {
27994	      this.push('{}'); // hashContexts
27995	      this.push('{}'); // hashTypes
27996	    }
27997	    this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
27998	  },
27999	  pushHash: function pushHash() {
28000	    if (this.hash) {
28001	      this.hashes.push(this.hash);
28002	    }
28003	    this.hash = { values: [], types: [], contexts: [], ids: [] };
28004	  },
28005	  popHash: function popHash() {
28006	    var hash = this.hash;
28007	    this.hash = this.hashes.pop();
28008
28009	    if (this.trackIds) {
28010	      this.push(this.objectLiteral(hash.ids));
28011	    }
28012	    if (this.stringParams) {
28013	      this.push(this.objectLiteral(hash.contexts));
28014	      this.push(this.objectLiteral(hash.types));
28015	    }
28016
28017	    this.push(this.objectLiteral(hash.values));
28018	  },
28019
28020	  // [pushString]
28021	  //
28022	  // On stack, before: ...
28023	  // On stack, after: quotedString(string), ...
28024	  //
vendor: 6,915 bytes, lines 28025-28238
28025	  // Push a quoted version of `string` onto the stack
28026	  pushString: function pushString(string) {
28027	    this.pushStackLiteral(this.quotedString(string));
28028	  },
28029
28030	  // [pushLiteral]
28031	  //
28032	  // On stack, before: ...
28033	  // On stack, after: value, ...
28034	  //
28035	  // Pushes a value onto the stack. This operation prevents
28036	  // the compiler from creating a temporary variable to hold
28037	  // it.
28038	  pushLiteral: function pushLiteral(value) {
28039	    this.pushStackLiteral(value);
28040	  },
28041
28042	  // [pushProgram]
28043	  //
28044	  // On stack, before: ...
28045	  // On stack, after: program(guid), ...
28046	  //
28047	  // Push a program expression onto the stack. This takes
28048	  // a compile-time guid and converts it into a runtime-accessible
28049	  // expression.
28050	  pushProgram: function pushProgram(guid) {
28051	    if (guid != null) {
28052	      this.pushStackLiteral(this.programExpression(guid));
28053	    } else {
28054	      this.pushStackLiteral(null);
28055	    }
28056	  },
28057
28058	  // [registerDecorator]
28059	  //
28060	  // On stack, before: hash, program, params..., ...
28061	  // On stack, after: ...
28062	  //
28063	  // Pops off the decorator's parameters, invokes the decorator,
28064	  // and inserts the decorator into the decorators list.
28065	  registerDecorator: function registerDecorator(paramSize, name) {
28066	    var foundDecorator = this.nameLookup('decorators', name, 'decorator'),
28067	        options = this.setupHelperArgs(name, paramSize);
28068
28069	    this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']);
28070	  },
28071
28072	  // [invokeHelper]
28073	  //
28074	  // On stack, before: hash, inverse, program, params..., ...
28075	  // On stack, after: result of helper invocation
28076	  //
28077	  // Pops off the helper's parameters, invokes the helper,
28078	  // and pushes the helper's return value onto the stack.
28079	  //
28080	  // If the helper is not found, `helperMissing` is called.
28081	  invokeHelper: function invokeHelper(paramSize, name, isSimple) {
28082	    var nonHelper = this.popStack(),
28083	        helper = this.setupHelper(paramSize, name),
28084	        simple = isSimple ? [helper.name, ' || '] : '';
28085
28086	    var lookup = ['('].concat(simple, nonHelper);
28087	    if (!this.options.strict) {
28088	      lookup.push(' || ', this.aliasable('helpers.helperMissing'));
28089	    }
28090	    lookup.push(')');
28091
28092	    this.push(this.source.functionCall(lookup, 'call', helper.callParams));
28093	  },
28094
28095	  // [invokeKnownHelper]
28096	  //
28097	  // On stack, before: hash, inverse, program, params..., ...
28098	  // On stack, after: result of helper invocation
28099	  //
28100	  // This operation is used when the helper is known to exist,
28101	  // so a `helperMissing` fallback is not required.
28102	  invokeKnownHelper: function invokeKnownHelper(paramSize, name) {
28103	    var helper = this.setupHelper(paramSize, name);
28104	    this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
28105	  },
28106
28107	  // [invokeAmbiguous]
28108	  //
28109	  // On stack, before: hash, inverse, program, params..., ...
28110	  // On stack, after: result of disambiguation
28111	  //
28112	  // This operation is used when an expression like `{{foo}}`
28113	  // is provided, but we don't know at compile-time whether it
28114	  // is a helper or a path.
28115	  //
28116	  // This operation emits more code than the other options,
28117	  // and can be avoided by passing the `knownHelpers` and
28118	  // `knownHelpersOnly` flags at compile-time.
28119	  invokeAmbiguous: function invokeAmbiguous(name, helperCall) {
28120	    this.useRegister('helper');
28121
28122	    var nonHelper = this.popStack();
28123
28124	    this.emptyHash();
28125	    var helper = this.setupHelper(0, name, helperCall);
28126
28127	    var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
28128
28129	    var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
28130	    if (!this.options.strict) {
28131	      lookup[0] = '(helper = ';
28132	      lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing'));
28133	    }
28134
28135	    this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']);
28136	  },
28137
28138	  // [invokePartial]
28139	  //
28140	  // On stack, before: context, ...
28141	  // On stack after: result of partial invocation
28142	  //
28143	  // This operation pops off a context, invokes a partial with that context,
28144	  // and pushes the result of the invocation back.
28145	  invokePartial: function invokePartial(isDynamic, name, indent) {
28146	    var params = [],
28147	        options = this.setupParams(name, 1, params);
28148
28149	    if (isDynamic) {
28150	      name = this.popStack();
28151	      delete options.name;
28152	    }
28153
28154	    if (indent) {
28155	      options.indent = JSON.stringify(indent);
28156	    }
28157	    options.helpers = 'helpers';
28158	    options.partials = 'partials';
28159	    options.decorators = 'container.decorators';
28160
28161	    if (!isDynamic) {
28162	      params.unshift(this.nameLookup('partials', name, 'partial'));
28163	    } else {
28164	      params.unshift(name);
28165	    }
28166
28167	    if (this.options.compat) {
28168	      options.depths = 'depths';
28169	    }
28170	    options = this.objectLiteral(options);
28171	    params.push(options);
28172
28173	    this.push(this.source.functionCall('container.invokePartial', '', params));
28174	  },
28175
28176	  // [assignToHash]
28177	  //
28178	  // On stack, before: value, ..., hash, ...
28179	  // On stack, after: ..., hash, ...
28180	  //
28181	  // Pops a value off the stack and assigns it to the current hash
28182	  assignToHash: function assignToHash(key) {
28183	    var value = this.popStack(),
28184	        context = undefined,
28185	        type = undefined,
28186	        id = undefined;
28187
28188	    if (this.trackIds) {
28189	      id = this.popStack();
28190	    }
28191	    if (this.stringParams) {
28192	      type = this.popStack();
28193	      context = this.popStack();
28194	    }
28195
28196	    var hash = this.hash;
28197	    if (context) {
28198	      hash.contexts[key] = context;
28199	    }
28200	    if (type) {
28201	      hash.types[key] = type;
28202	    }
28203	    if (id) {
28204	      hash.ids[key] = id;
28205	    }
28206	    hash.values[key] = value;
28207	  },
28208
28209	  pushId: function pushId(type, name, child) {
28210	    if (type === 'BlockParam') {
28211	      this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : ''));
28212	    } else if (type === 'PathExpression') {
28213	      this.pushString(name);
28214	    } else if (type === 'SubExpression') {
28215	      this.pushStackLiteral('true');
28216	    } else {
28217	      this.pushStackLiteral('null');
28218	    }
28219	  },
28220
28221	  // HELPERS
28222
28223	  compiler: JavaScriptCompiler,
28224
28225	  compileChildren: function compileChildren(environment, options) {
28226	    var children = environment.children,
28227	        child = undefined,
28228	        compiler = undefined;
28229
28230	    for (var i = 0, l = children.length; i < l; i++) {
28231	      child = children[i];
28232	      compiler = new this.compiler(); // eslint-disable-line new-cap
28233
28234	      var existing = this.matchExistingProgram(child);
28235
28236	      if (existing == null) {
28237	        this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
28238	        var index = this.context.programs.length
vendor: 8,183 bytes, lines 28238-28526
28238;
28239	        child.index = index;
28240	        child.name = 'program' + index;
28241	        this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
28242	        this.context.decorators[index] = compiler.decorators;
28243	        this.context.environments[index] = child;
28244
28245	        this.useDepths = this.useDepths || compiler.useDepths;
28246	        this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
28247	        child.useDepths = this.useDepths;
28248	        child.useBlockParams = this.useBlockParams;
28249	      } else {
28250	        child.index = existing.index;
28251	        child.name = 'program' + existing.index;
28252
28253	        this.useDepths = this.useDepths || existing.useDepths;
28254	        this.useBlockParams = this.useBlockParams || existing.useBlockParams;
28255	      }
28256	    }
28257	  },
28258	  matchExistingProgram: function matchExistingProgram(child) {
28259	    for (var i = 0, len = this.context.environments.length; i < len; i++) {
28260	      var environment = this.context.environments[i];
28261	      if (environment && environment.equals(child)) {
28262	        return environment;
28263	      }
28264	    }
28265	  },
28266
28267	  programExpression: function programExpression(guid) {
28268	    var child = this.environment.children[guid],
28269	        programParams = [child.index, 'data', child.blockParams];
28270
28271	    if (this.useBlockParams || this.useDepths) {
28272	      programParams.push('blockParams');
28273	    }
28274	    if (this.useDepths) {
28275	      programParams.push('depths');
28276	    }
28277
28278	    return 'container.program(' + programParams.join(', ') + ')';
28279	  },
28280
28281	  useRegister: function useRegister(name) {
28282	    if (!this.registers[name]) {
28283	      this.registers[name] = true;
28284	      this.registers.list.push(name);
28285	    }
28286	  },
28287
28288	  push: function push(expr) {
28289	    if (!(expr instanceof Literal)) {
28290	      expr = this.source.wrap(expr);
28291	    }
28292
28293	    this.inlineStack.push(expr);
28294	    return expr;
28295	  },
28296
28297	  pushStackLiteral: function pushStackLiteral(item) {
28298	    this.push(new Literal(item));
28299	  },
28300
28301	  pushSource: function pushSource(source) {
28302	    if (this.pendingContent) {
28303	      this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
28304	      this.pendingContent = undefined;
28305	    }
28306
28307	    if (source) {
28308	      this.source.push(source);
28309	    }
28310	  },
28311
28312	  replaceStack: function replaceStack(callback) {
28313	    var prefix = ['('],
28314	        stack = undefined,
28315	        createdStack = undefined,
28316	        usedLiteral = undefined;
28317
28318	    /* istanbul ignore next */
28319	    if (!this.isInline()) {
28320	      throw new _exception2['default']('replaceStack on non-inline');
28321	    }
28322
28323	    // We want to merge the inline statement into the replacement statement via ','
28324	    var top = this.popStack(true);
28325
28326	    if (top instanceof Literal) {
28327	      // Literals do not need to be inlined
28328	      stack = [top.value];
28329	      prefix = ['(', stack];
28330	      usedLiteral = true;
28331	    } else {
28332	      // Get or create the current stack name for use by the inline
28333	      createdStack = true;
28334	      var _name = this.incrStack();
28335
28336	      prefix = ['((', this.push(_name), ' = ', top, ')'];
28337	      stack = this.topStack();
28338	    }
28339
28340	    var item = callback.call(this, stack);
28341
28342	    if (!usedLiteral) {
28343	      this.popStack();
28344	    }
28345	    if (createdStack) {
28346	      this.stackSlot--;
28347	    }
28348	    this.push(prefix.concat(item, ')'));
28349	  },
28350
28351	  incrStack: function incrStack() {
28352	    this.stackSlot++;
28353	    if (this.stackSlot > this.stackVars.length) {
28354	      this.stackVars.push('stack' + this.stackSlot);
28355	    }
28356	    return this.topStackName();
28357	  },
28358	  topStackName: function topStackName() {
28359	    return 'stack' + this.stackSlot;
28360	  },
28361	  flushInline: function flushInline() {
28362	    var inlineStack = this.inlineStack;
28363	    this.inlineStack = [];
28364	    for (var i = 0, len = inlineStack.length; i < len; i++) {
28365	      var entry = inlineStack[i];
28366	      /* istanbul ignore if */
28367	      if (entry instanceof Literal) {
28368	        this.compileStack.push(entry);
28369	      } else {
28370	        var stack = this.incrStack();
28371	        this.pushSource([stack, ' = ', entry, ';']);
28372	        this.compileStack.push(stack);
28373	      }
28374	    }
28375	  },
28376	  isInline: function isInline() {
28377	    return this.inlineStack.length;
28378	  },
28379
28380	  popStack: function popStack(wrapped) {
28381	    var inline = this.isInline(),
28382	        item = (inline ? this.inlineStack : this.compileStack).pop();
28383
28384	    if (!wrapped && item instanceof Literal) {
28385	      return item.value;
28386	    } else {
28387	      if (!inline) {
28388	        /* istanbul ignore next */
28389	        if (!this.stackSlot) {
28390	          throw new _exception2['default']('Invalid stack pop');
28391	        }
28392	        this.stackSlot--;
28393	      }
28394	      return item;
28395	    }
28396	  },
28397
28398	  topStack: function topStack() {
28399	    var stack = this.isInline() ? this.inlineStack : this.compileStack,
28400	        item = stack[stack.length - 1];
28401
28402	    /* istanbul ignore if */
28403	    if (item instanceof Literal) {
28404	      return item.value;
28405	    } else {
28406	      return item;
28407	    }
28408	  },
28409
28410	  contextName: function contextName(context) {
28411	    if (this.useDepths && context) {
28412	      return 'depths[' + context + ']';
28413	    } else {
28414	      return 'depth' + context;
28415	    }
28416	  },
28417
28418	  quotedString: function quotedString(str) {
28419	    return this.source.quotedString(str);
28420	  },
28421
28422	  objectLiteral: function objectLiteral(obj) {
28423	    return this.source.objectLiteral(obj);
28424	  },
28425
28426	  aliasable: function aliasable(name) {
28427	    var ret = this.aliases[name];
28428	    if (ret) {
28429	      ret.referenceCount++;
28430	      return ret;
28431	    }
28432
28433	    ret = this.aliases[name] = this.source.wrap(name);
28434	    ret.aliasable = true;
28435	    ret.referenceCount = 1;
28436
28437	    return ret;
28438	  },
28439
28440	  setupHelper: function setupHelper(paramSize, name, blockHelper) {
28441	    var params = [],
28442	        paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
28443	    var foundHelper = this.nameLookup('helpers', name, 'helper'),
28444	        callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})');
28445
28446	    return {
28447	      params: params,
28448	      paramsInit: paramsInit,
28449	      name: foundHelper,
28450	      callParams: [callContext].concat(params)
28451	    };
28452	  },
28453
28454	  setupParams: function setupParams(helper, paramSize, params) {
28455	    var options = {},
28456	        contexts = [],
28457	        types = [],
28458	        ids = [],
28459	        objectArgs = !params,
28460	        param = undefined;
28461
28462	    if (objectArgs) {
28463	      params = [];
28464	    }
28465
28466	    options.name = this.quotedString(helper);
28467	    options.hash = this.popStack();
28468
28469	    if (this.trackIds) {
28470	      options.hashIds = this.popStack();
28471	    }
28472	    if (this.stringParams) {
28473	      options.hashTypes = this.popStack();
28474	      options.hashContexts = this.popStack();
28475	    }
28476
28477	    var inverse = this.popStack(),
28478	        program = this.popStack();
28479
28480	    // Avoid setting fn and inverse if neither are set. This allows
28481	    // helpers to do a check for `if (options.fn)`
28482	    if (program || inverse) {
28483	      options.fn = program || 'container.noop';
28484	      options.inverse = inverse || 'container.noop';
28485	    }
28486
28487	    // The parameters go on to the stack in order (making sure that they are evaluated in order)
28488	    // so we need to pop them off the stack in reverse order
28489	    var i = paramSize;
28490	    while (i--) {
28491	      param = this.popStack();
28492	      params[i] = param;
28493
28494	      if (this.trackIds) {
28495	        ids[i] = this.popStack();
28496	      }
28497	      if (this.stringParams) {
28498	        types[i] = this.popStack();
28499	        contexts[i] = this.popStack();
28500	      }
28501	    }
28502
28503	    if (objectArgs) {
28504	      options.args = this.source.generateArray(params);
28505	    }
28506
28507	    if (this.trackIds) {
28508	      options.ids = this.source.generateArray(ids);
28509	    }
28510	    if (this.stringParams) {
28511	      options.types = this.source.generateArray(types);
28512	      options.contexts = this.source.generateArray(contexts);
28513	    }
28514
28515	    if (this.options.data) {
28516	      options.data = 'data';
28517	    }
28518	    if (this.useBlockParams) {
28519	      options.blockParams = 'blockParams';
28520	    }
28521	    return options;
28522	  },
28523
28524	  setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) {
28525	    var options = this.setupParams(helper, paramSize, params);
28526	    options
vendor: 1,005 bytes, lines 28526-28549
28526 = this.objectLiteral(options);
28527	    if (useRegister) {
28528	      this.useRegister('options');
28529	      params.push('options');
28530	      return ['options=', options];
28531	    } else if (params) {
28532	      params.push(options);
28533	      return '';
28534	    } else {
28535	      return options;
28536	    }
28537	  }
28538	};
28539
28540	(function () {
28541	  var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' ');
28542
28543	  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
28544
28545	  for (var i = 0, l = reservedWords.length; i < l; i++) {
28546	    compilerWords[reservedWords[i]] = true;
28547	  }
28548	})();
28549
vendor: 4,122 bytes, lines 28550-28701
28550	JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
28551	  return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
28552	};
28553
28554	function strictLookup(requireTerminal, compiler, parts, type) {
28555	  var stack = compiler.popStack(),
28556	      i = 0,
28557	      len = parts.length;
28558	  if (requireTerminal) {
28559	    len--;
28560	  }
28561
28562	  for (; i < len; i++) {
28563	    stack = compiler.nameLookup(stack, parts[i], type);
28564	  }
28565
28566	  if (requireTerminal) {
28567	    return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')'];
28568	  } else {
28569	    return stack;
28570	  }
28571	}
28572
28573	exports['default'] = JavaScriptCompiler;
28574	module.exports = exports['default'];
28575
28576/***/ }),
28577/* 43 */
28578/***/ (function(module, exports, __webpack_require__) {
28579
28580	/* global define */
28581	'use strict';
28582
28583	exports.__esModule = true;
28584
28585	var _utils = __webpack_require__(5);
28586
28587	var SourceNode = undefined;
28588
28589	try {
28590	  /* istanbul ignore next */
28591	  if (false) {
28592	    // We don't support this in AMD environments. For these environments, we asusme that
28593	    // they are running on the browser and thus have no need for the source-map library.
28594	    var SourceMap = require('source-map');
28595	    SourceNode = SourceMap.SourceNode;
28596	  }
28597	} catch (err) {}
28598	/* NOP */
28599
28600	/* istanbul ignore if: tested but not covered in istanbul due to dist build  */
28601	if (!SourceNode) {
28602	  SourceNode = function (line, column, srcFile, chunks) {
28603	    this.src = '';
28604	    if (chunks) {
28605	      this.add(chunks);
28606	    }
28607	  };
28608	  /* istanbul ignore next */
28609	  SourceNode.prototype = {
28610	    add: function add(chunks) {
28611	      if (_utils.isArray(chunks)) {
28612	        chunks = chunks.join('');
28613	      }
28614	      this.src += chunks;
28615	    },
28616	    prepend: function prepend(chunks) {
28617	      if (_utils.isArray(chunks)) {
28618	        chunks = chunks.join('');
28619	      }
28620	      this.src = chunks + this.src;
28621	    },
28622	    toStringWithSourceMap: function toStringWithSourceMap() {
28623	      return { code: this.toString() };
28624	    },
28625	    toString: function toString() {
28626	      return this.src;
28627	    }
28628	  };
28629	}
28630
28631	function castChunk(chunk, codeGen, loc) {
28632	  if (_utils.isArray(chunk)) {
28633	    var ret = [];
28634
28635	    for (var i = 0, len = chunk.length; i < len; i++) {
28636	      ret.push(codeGen.wrap(chunk[i], loc));
28637	    }
28638	    return ret;
28639	  } else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
28640	    // Handle primitives that the SourceNode will throw up on
28641	    return chunk + '';
28642	  }
28643	  return chunk;
28644	}
28645
28646	function CodeGen(srcFile) {
28647	  this.srcFile = srcFile;
28648	  this.source = [];
28649	}
28650
28651	CodeGen.prototype = {
28652	  isEmpty: function isEmpty() {
28653	    return !this.source.length;
28654	  },
28655	  prepend: function prepend(source, loc) {
28656	    this.source.unshift(this.wrap(source, loc));
28657	  },
28658	  push: function push(source, loc) {
28659	    this.source.push(this.wrap(source, loc));
28660	  },
28661
28662	  merge: function merge() {
28663	    var source = this.empty();
28664	    this.each(function (line) {
28665	      source.add(['  ', line, '\n']);
28666	    });
28667	    return source;
28668	  },
28669
28670	  each: function each(iter) {
28671	    for (var i = 0, len = this.source.length; i < len; i++) {
28672	      iter(this.source[i]);
28673	    }
28674	  },
28675
28676	  empty: function empty() {
28677	    var loc = this.currentLocation || { start: {} };
28678	    return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
28679	  },
28680	  wrap: function wrap(chunk) {
28681	    var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1];
28682
28683	    if (chunk instanceof SourceNode) {
28684	      return chunk;
28685	    }
28686
28687	    chunk = castChunk(chunk, this, loc);
28688
28689	    return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
28690	  },
28691
28692	  functionCall: function functionCall(fn, type, params) {
28693	    params = this.generateList(params);
28694	    return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
28695	  },
28696
28697	  quotedString: function quotedString(str) {
28698	    return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
28699	    .replace(/\u2029/g, '\\u2029') + '"';
28700	  },
28701
28702	  objectLiteral: function objectLiteral(obj) {
28703	    var pairs = [];
28704
28705	    for (var key in obj) {
28706	      if (obj.hasOwnProperty(key)) {
28707	        var value = castChunk(obj[key], this);
28708	        if (value !== 'undefined') {
28709	          pairs.push([this.quotedString(key), ':', value]);
28710	        }
28711	      }
28712	    }
28713
28714	    var ret = this.generateList(pairs);
28715	    ret.prepend('{');
28716	    ret.add('}');
28717	    return ret;
28718	  },
28719
28720	  generateList: function generateList(entries) {
28721	    var ret = this.empty();
28722
28723	    for (var i = 0, len = entries.length; i < len; i++) {
28724	      if (i) {
28725	        ret.add(',');
28726	      }
28727
28728	      ret.add(castChunk(entries[i], this));
28729	    }
28730
28731	    return ret;
28732	  },
28733
28734	  generateArray: function generateArray(entries) {
28735	    var ret = this.generateList(entries);
28736	    ret.prepend('[');
28737	    ret.add(']');
28738
28739	    return ret;
28740	  }
28741	};
28742
28743	exports['default'] = CodeGen;
28744	module.exports = exports['default'];
28745
28746/***/ })
28747/******/ ])
28748});
28749;
28750/*!
28751* jquery.inputmask.bundle.js
28752* https://github.com/RobinHerbots/Inputmask
28753* Copyright (c) 2010 - 2019 Robin Herbots
28754* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
28755* Version: 4.0.8
28756*/
28757
28758(function(modules) {
28759    var installedModules = {};
28760    function __webpack_require__(moduleId) {
28761        if (installedModules[moduleId]) {
28762            return installedModules[moduleId].exports;
28763        }
28764        var module = installedModules[moduleId] = {
28765            i: moduleId,
28766            l: false,
28767            exports: {}
28768        };
28769        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
28770        module.l = true;
28771        return module.exports;
28772    }
28773    __webpack_require__.m = modules;
28774    __webpack_require__.c = installedModules;
28775    __webpack_require__.d = function(exports, name, getter) {
28776        if (!__webpack_require__.o(exports, name)) {
28777            Object.defineProperty(exports, name, {
28778                enumerable: true,
28779                get: getter
28780            });
28781        }
28782    };
28783    __webpack_require__.r = function(exports) {
28784        if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
28785            Object.defineProperty(exports, Symbol.toStringTag, {
28786                value: "Module"
28787            });
28788        }
28789        Object.defineProperty(exports, "__esModule", {
28790            value: true
28791        });
28792    };
28793    __webpack_require__.t = function(value, mode) {
28794        if (mode & 1) value = __webpack_require__(value);
28795        if (mode & 8) return value;
28796        if (mode & 4 && typeof value === "object" && value && value.__esModule) return value;
28797        var ns = Object.create(null);
28798        __webpack_require__.r(ns);
28799        Object.defineProperty(ns, "default", {
28800            enumerable: true,
28801            value: value
28802        });
28803        if (mode & 2 && typeof value != "string") for (var key in value) __webpack_require__.d(ns, key, function(key) {
28804            return value[key];
28805        }.bind(null, key));
28806        return ns;
28807    };
28808    __webpack_require__.n = function(module) {
28809        var getter = module && module.__esModule ? function getDefault() {
28810            return module["default"];
28811        } : function getModuleExports() {
28812            return module;
28813        };
28814        __webpack_require__.d(getter, "a", getter);
28815        return getter;
28816    };
28817    __webpack_require__.o = function(object, property) {
28818        return Object.prototype.hasOwnProperty.call(object, property);
28819    };
28820    __webpack_require__.p = "";
28821    return __webpack_require__(__webpack_require__.s = 0);
28822})([ function(module, exports, __webpack_require__) {
28823    "use strict";
28824    __webpack_require__(1);
28825    __webpack_require__(6);
28826    __webpack_require__(7);
28827    var _inputmask = __webpack_require__(2);
28828    var _inputmask2 = _interopRequireDefault(_inputmask);
28829    var _inputmask3 = __webpack_require__(3);
28830    var _inputmask4 = _interopRequireDefault(_inputmask3);
28831    var _jquery = __webpack_require__(4);
28832    var _jquery2 = _interopRequireDefault(_jquery);
28833    function _interopRequireDefault(obj) {
28834        return obj && obj.__esModule ? obj : {
28835            default: obj
28836        };
28837    }
28838    if (_inputmask4.default === _jquery2.default) {
28839        __webpack_require__(8);
28840    }
28841    window.Inputmask = _inputmask2.default;
28842}, function(module, exports, __webpack_require__) {
28843    "use strict";
28844    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
28845    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
28846        return typeof obj;
28847    } : function(obj) {
28848        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
28849    };
28850    (function(factory) {
28851        if (true) {
28852            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
28853            __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
28854            __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
28855        } else {}
28856    })(function(Inputmask) {
28857        Inputmask.extendDefinitions({
28858            A: {
28859                validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
28860                casing: "upper"
28861            },
28862            "&": {
28863                validator: "[0-9A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
28864                casing: "upper"
28865            },
28866            "#": {
28867                validator: "[0-9A-Fa-f]",
28868                casing: "upper"
28869            }
28870        });
28871        Inputmask.extendAliases({
28872            cssunit: {
28873                regex: "[+-]?[0-9]+\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)"
28874            },
28875            url: {
28876                regex: "(https?|ftp)//.*",
28877                autoUnmask: false
28878            },
28879            ip: {
28880                mask: "i[i[i]].i[i[i]].i[i[i]].i[i[i]]",
28881                definitions: {
28882                    i: {
28883                        validator: function validator(chrs, maskset, pos, strict, opts) {
28884                            if (pos - 1 > -1 && maskset.buffer[pos - 1] !== ".") {
28885                                chrs = maskset.buffer[pos - 1] + chrs;
28886                                if (pos - 2 > -1 && maskset.buffer[pos - 2] !== ".") {
28887                                    chrs = maskset.buffer[pos - 2] + chrs;
28888                                } else chrs = "0" + chrs;
28889                            } else chrs = "00" + chrs;
28890                            return new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs);
28891                        }
28892                    }
28893                },
28894                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
28895                    return maskedValue;
28896                },
28897                inputmode: "numeric"
28898            },
28899            email: {
28900                mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",
28901                greedy: false,
28902                casing: "lower",
28903                onBeforePaste: function onBeforePaste(pastedValue, opts) {
28904                    pastedValue = pastedValue.toLowerCase();
28905                    return pastedValue.replace("mailto:", "");
28906                },
28907                definitions: {
28908                    "*": {
28909                        validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5!#$%&'*+/=?^_`{|}~-]"
28910                    },
28911                    "-": {
28912                        validator: "[0-9A-Za-z-]"
28913                    }
28914                },
28915                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
28916                    return maskedValue;
28917                },
28918                inputmode: "email"
28919            },
28920            mac: {
28921                mask: "##:##:##:##:##:##"
28922            },
28923            vin: {
28924                mask: "V{13}9{4}",
28925                definitions: {
28926                    V: {
28927                        validator: "[A-HJ-NPR-Za-hj-npr-z\\d]",
28928                        casing: "upper"
28929                    }
28930                },
28931                clearIncomplete: true,
28932                autoUnmask: true
28933            }
28934        });
28935        return Inputmask;
28936    });
28937}, function(module, exports, __webpack_require__) {
28938    "use strict";
28939    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
28940    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
28941        return typeof obj;
28942    } : function(obj) {
28943        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
28944    };
28945    (function(factory) {
28946        if (true) {
28947            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(3), __webpack_require__(5) ], 
28948            __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__, 
28949            __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
28950        } else {}
28951    })(function($, window, undefined) {
28952        var document = window.document, ua = navigator.userAgent, ie = ua.indexOf("MSIE ") > 0 || ua.indexOf("Trident/") > 0, mobile = isInputEventSupported("touchstart"), iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile;
28953        function Inputmask(alias, options, internal) {
28954            if (!(this instanceof Inputmask)) {
28955                return new Inputmask(alias, options, internal);
28956            }
28957            this.el = undefined;
28958            this.events = {};
28959            this.maskset = undefined;
28960            this.refreshValue = false;
28961            if (internal !== true) {
28962                if ($.isPlainObject(alias)) {
28963                    options = alias;
28964                } else {
28965                    options = options || {};
28966                    if (alias) options.alias = alias;
28967                }
28968                this.opts = $.extend(true, {}, this.defaults, options);
28969                this.noMasksCache = options && options.definitions !== undefined;
28970                this.userOptions = options || {};
28971                this.isRTL = this.opts.numericInput;
28972                resolveAlias(this.opts.alias, options, this.opts);
28973            }
28974        }
28975        Inputmask.prototype = {
28976            dataAttribute: "data-inputmask",
28977            defaults: {
28978                placeholder: "_",
28979                optionalmarker: [ "[", "]" ],
28980                quantifiermarker: [ "{", "}" ],
28981                groupmarker: [ "(", ")" ],
28982                alternatormarker: "|",
28983                escapeChar: "\\",
28984                mask: null,
28985                regex: null,
28986                oncomplete: $.noop,
28987                onincomplete: $.noop,
28988                oncleared: $.noop,
28989                repeat: 0,
28990                greedy: false,
28991                autoUnmask: false,
28992                removeMaskOnSubmit: false,
28993                clearMaskOnLostFocus: true,
28994                insertMode: true,
28995                clearIncomplete: false,
28996                alias: null,
28997                onKeyDown: $.noop,
28998                onBeforeMask: null,
28999                onBeforePaste: function onBeforePaste(pastedValue, opts) {
29000                    return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue;
29001                },
29002                onBeforeWrite: null,
29003                onUnMask: null,
29004                showMaskOnFocus: true,
29005                showMaskOnHover: true,
29006                onKeyValidation: $.noop,
29007                skipOptionalPartCharacter: " ",
29008                numericInput: false,
29009                rightAlign: false,
29010                undoOnEscape: true,
29011                radixPoint: "",
29012                _radixDance: false,
29013                groupSeparator: "",
29014                keepStatic: null,
29015                positionCaretOnTab: true,
29016                tabThrough: false,
29017                supportsInputType: [ "text", "tel", "url", "password", "search" ],
29018                ignorables: [ 8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 229 ],
29019                isComplete: null,
29020                preValidation: null,
29021                postValidation: null,
29022                staticDefinitionSymbol: undefined,
29023                jitMasking: false,
29024                nullable: true,
29025                inputEventOnly: false,
29026                noValuePatching: false,
29027                positionCaretOnClick: "lvp",
29028                casing: null,
29029                inputmode: "verbatim",
29030                colorMask: false,
29031                disablePredictiveText: false,
29032                importDataAttributes: true,
29033                shiftPositions: true
29034            },
29035            definitions: {
29036                9: {
29037                    validator: "[0-9\uff11-\uff19]",
29038                    definitionSymbol: "*"
29039                },
29040                a: {
29041                    validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",
29042                    definitionSymbol: "*"
29043                },
29044                "*": {
29045                    validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]"
29046                }
29047            },
29048            aliases: {},
29049            masksCache: {},
29050            mask: function mask(elems) {
29051                var that = this;
29052                function importAttributeOptions(npt, opts, userOptions, dataAttribute) {
29053                    if (opts.importDataAttributes === true) {
29054                        var attrOptions = npt.getAttribute(dataAttribute), option, dataoptions, optionData, p;
29055                        var importOption = function importOption(option, optionData) {
29056                            optionData = optionData !== undefined ? optionData : npt.getAttribute(dataAttribute + "-" + option);
29057                            if (optionData !== null) {
29058                                if (typeof optionData === "string") {
29059                                    if (option.indexOf("on") === 0) optionData = window[optionData];
29059 else if (optionData === "false") optionData = false; else if (optionData === "true") optionData = true;
29060                                }
29061                                userOptions[option] = optionData;
29062                            }
29063                        };
29064                        if (attrOptions && attrOptions !== "") {
29065                            attrOptions = attrOptions.replace(/'/g, '"');
29066                            dataoptions = JSON.parse("{" + attrOptions + "}");
29067                        }
29068                        if (dataoptions) {
29069                            optionData = undefined;
29070                            for (p in dataoptions) {
29071                                if (p.toLowerCase() === "alias") {
29072                                    optionData = dataoptions[p];
29073                                    break;
29074                                }
29075                            }
29076                        }
29077                        importOption("alias", optionData);
29078                        if (userOptions.alias) {
29079                            resolveAlias(userOptions.alias, userOptions, opts);
29080                        }
29081                        for (option in opts) {
29082                            if (dataoptions) {
29083                                optionData = undefined;
29084                                for (p in dataoptions) {
29085                                    if (p.toLowerCase() === option.toLowerCase()) {
29086                                        optionData = dataoptions[p];
29087                                        break;
29088                                    }
29089                                }
29090                            }
29091                            importOption(option, optionData);
29092                        }
29093                    }
29094                    $.extend(true, opts, userOptions);
29095                    if (npt.dir === "rtl" || opts.rightAlign) {
29096                        npt.style.textAlign = "right";
29097                    }
29098                    if (npt.dir === "rtl" || opts.numericInput) {
29099                        npt.dir = "ltr";
29100                        npt.removeAttribute("dir");
29101                        opts.isRTL = true;
29102                    }
29103                    return Object.keys(userOptions).length;
29104                }
29105                if (typeof elems === "string") {
29106                    elems = document.getElementById(elems) || document.querySelectorAll(elems);
29107                }
29108                elems = elems.nodeName ? [ elems ] : elems;
29109                $.each(elems, function(ndx, el) {
29110                    var scopedOpts = $.extend(true, {}, that.opts);
29111                    if (importAttributeOptions(el, scopedOpts, $.extend(true, {}, that.userOptions), that.dataAttribute)) {
29112                        var maskset = generateMaskSet(scopedOpts, that.noMasksCache);
29113                        if (maskset !== undefined) {
29114                            if (el.inputmask !== undefined) {
29115                                el.inputmask.opts.autoUnmask = true;
29116                                el.inputmask.remove();
29117                            }
29118                            el.inputmask = new Inputmask(undefined, undefined, true);
29119                            el.inputmask.opts = scopedOpts;
29120                            el.inputmask.noMasksCache = that.noMasksCache;
29121                            el.inputmask.userOptions = $.extend(true, {}, that.userOptions);
29122                            el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput;
29123                            el.inputmask.el = el;
29124                            el.inputmask.maskset = maskset;
29125                            $.data(el, "_inputmask_opts", scopedOpts);
29126                            maskScope.call(el.inputmask, {
29127                                action: "mask"
29128                            });
29129                        }
29130                    }
29131                });
29132                return elems && elems[0] ? elems[0].inputmask || this : this;
29133            },
29134            option: function option(options, noremask) {
29135                if (typeof options === "string") {
29136                    return this.opts[options];
29137                } else if ((typeof options === "undefined" ? "undefined" : _typeof(options)) === "object") {
29138                    $.extend(this.userOptions, options);
29139                    if (this.el && noremask !== true) {
29140                        this.mask(this.el);
29141                    }
29142                    return this;
29143                }
29144            },
29145            unmaskedvalue: function unmaskedvalue(value) {
29146                this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
29147                return maskScope.call(this, {
29148                    action: "unmaskedvalue",
29149                    value: value
29150                });
29151            },
29152            remove: function remove() {
29153                return maskScope.call(this, {
29154                    action: "remove"
29155                });
29156            },
29157            getemptymask: function getemptymask() {
29158                this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
29159                return maskScope.call(this, {
29160                    action: "getemptymask"
29161                });
29162            },
29163            hasMaskedValue: function hasMaskedValue() {
29164                return !this.opts.autoUnmask;
29165            },
29166            isComplete: function isComplete() {
29167                this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
29168                return maskScope.call(this, {
29169                    action: "isComplete"
29170                });
29171            },
29172            getmetadata: function getmetadata() {
29173                this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
29174                return maskScope.call(this, {
29175                    action: "getmetadata"
29176                });
29177            },
29178            isValid: function isValid(value) {
29179                this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
29180                return maskScope.call(this, {
29181                    action: "isValid",
29182                    value: value
29183                });
29184            },
29185            format: function format(value, metadata) {
29186                this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache);
29187                return maskScope.call(this, {
29188                    action: "format",
29189                    value: value,
29190                    metadata: metadata
29191                });
29192            },
29193            setValue: function setValue(value) {
29194                if (this.el) {
29195                    $(this.el).trigger("setvalue", [ value ]);
29196                }
29197            },
29198            analyseMask: function analyseMask(mask, regexMask, opts) {
29199                var tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?(?:\|[0-9\+\*]*)?\})|[^.?*+^${[]()|\\]+|./g, regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, escaped = false, currentToken = new MaskToken(), match, m, openenings = [], maskTokens = [], openingToken, currentOpeningToken, alternator, lastMatch, groupToken;
29200                function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) {
29201                    this.matches = [];
29202                    this.openGroup = isGroup || false;
29203                    this.alternatorGroup = false;
29204                    this.isGroup = isGroup || false;
29205                    this.isOptional = isOptional || false;
29206                    this.isQuantifier = isQuantifier || false;
29207                    this.isAlternator = isAlternator || false;
29208                    this.quantifier = {
29209                        min: 1,
29210                        max: 1
29211                    };
29212                }
29213                function insertTestDefinition(mtoken, element, position) {
29214                    position = position !== undefined ? position : mtoken.matches.length;
29215                    var prevMatch = mtoken.matches[position - 1];
29216                    if (regexMask) {
29217                        if (element.indexOf("[") === 0 || escaped && /\\d|\\s|\\w]/i.test(element) || element === ".") {
29218                            mtoken.matches.splice(position++, 0, {
29219                                fn: new RegExp(element, opts.casing ? "i" : ""),
29220                                optionality: false,
29221                                newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== element,
29222                                casing: null,
29223                                def: element,
29224                                placeholder: undefined,
29225                                nativeDef: element
29226                            });
29227                        } else {
29228                            if (escaped) element = element[element.length - 1];
29229                            $.each(element.split(""), function(ndx, lmnt) {
29230                                prevMatch = mtoken.matches[position - 1];
29231                                mtoken.matches.splice(position++, 0, {
29232                                    fn: null,
29233                                    optionality: false,
29234                                    newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== lmnt && prevMatch.fn !== null,
29235                                    casing: null,
29236                                    def: opts.staticDefinitionSymbol || lmnt,
29237                                    placeholder: opts.staticDefinitionSymbol !== undefined ? lmnt : undefined,
29238                                    nativeDef: (escaped ? "'" : "") + lmnt
29239                                });
29240                            });
29241                        }
29242                        escaped = false;
29243                    } else {
29244                        var maskdef = (opts.definitions ? opts.definitions[element] : undefined) || Inputmask.prototype.definitions[element];
29245                        if (maskdef && !escaped) {
29246                            mtoken.matches.splice(position++, 0, {
29247                                fn: maskdef.validator ? typeof maskdef.validator == "string" ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() {
29248                                    this.test = maskdef.validator;
29249                                }() : new RegExp("."),
29250                                optionality: false,
29251                                newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== (maskdef.definitionSymbol || element),
29252                                casing: maskdef.casing,
29253                                def: maskdef.definitionSymbol || element,
29254                                placeholder: maskdef.placeholder,
29255                                nativeDef: element
29256                            });
29257                        } else {
29258                            mtoken.matches.splice(position++, 0, {
29259                                fn: null,
29260                                optionality: false,
29261                                newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== element && prevMatch.fn !== null,
29262                                casing: null,
29263                                def: opts.staticDefinitionSymbol || element,
29264                                placeholder: opts.staticDefinitionSymbol !== undefined ? element : undefined,
29265                                nativeDef: (escaped ? "'" : "") + element
29266                            });
29267                            escaped = false;
vendor: 5,552 bytes, lines 29268-29382
29268                        }
29269                    }
29270                }
29271                function verifyGroupMarker(maskToken) {
29272                    if (maskToken && maskToken.matches) {
29273                        $.each(maskToken.matches, function(ndx, token) {
29274                            var nextToken = maskToken.matches[ndx + 1];
29275                            if ((nextToken === undefined || nextToken.matches === undefined || nextToken.isQuantifier === false) && token && token.isGroup) {
29276                                token.isGroup = false;
29277                                if (!regexMask) {
29278                                    insertTestDefinition(token, opts.groupmarker[0], 0);
29279                                    if (token.openGroup !== true) {
29280                                        insertTestDefinition(token, opts.groupmarker[1]);
29281                                    }
29282                                }
29283                            }
29284                            verifyGroupMarker(token);
29285                        });
29286                    }
29287                }
29288                function defaultCase() {
29289                    if (openenings.length > 0) {
29290                        currentOpeningToken = openenings[openenings.length - 1];
29291                        insertTestDefinition(currentOpeningToken, m);
29292                        if (currentOpeningToken.isAlternator) {
29293                            alternator = openenings.pop();
29294                            for (var mndx = 0; mndx < alternator.matches.length; mndx++) {
29295                                if (alternator.matches[mndx].isGroup) alternator.matches[mndx].isGroup = false;
29296                            }
29297                            if (openenings.length > 0) {
29298                                currentOpeningToken = openenings[openenings.length - 1];
29299                                currentOpeningToken.matches.push(alternator);
29300                            } else {
29301                                currentToken.matches.push(alternator);
29302                            }
29303                        }
29304                    } else {
29305                        insertTestDefinition(currentToken, m);
29306                    }
29307                }
29308                function reverseTokens(maskToken) {
29309                    function reverseStatic(st) {
29310                        if (st === opts.optionalmarker[0]) st = opts.optionalmarker[1]; else if (st === opts.optionalmarker[1]) st = opts.optionalmarker[0]; else if (st === opts.groupmarker[0]) st = opts.groupmarker[1]; else if (st === opts.groupmarker[1]) st = opts.groupmarker[0];
29311                        return st;
29312                    }
29313                    maskToken.matches = maskToken.matches.reverse();
29314                    for (var match in maskToken.matches) {
29315                        if (maskToken.matches.hasOwnProperty(match)) {
29316                            var intMatch = parseInt(match);
29317                            if (maskToken.matches[match].isQuantifier && maskToken.matches[intMatch + 1] && maskToken.matches[intMatch + 1].isGroup) {
29318                                var qt = maskToken.matches[match];
29319                                maskToken.matches.splice(match, 1);
29320                                maskToken.matches.splice(intMatch + 1, 0, qt);
29321                            }
29322                            if (maskToken.matches[match].matches !== undefined) {
29323                                maskToken.matches[match] = reverseTokens(maskToken.matches[match]);
29324                            } else {
29325                                maskToken.matches[match] = reverseStatic(maskToken.matches[match]);
29326                            }
29327                        }
29328                    }
29329                    return maskToken;
29330                }
29331                function groupify(matches) {
29332                    var groupToken = new MaskToken(true);
29333                    groupToken.openGroup = false;
29334                    groupToken.matches = matches;
29335                    return groupToken;
29336                }
29337                if (regexMask) {
29338                    opts.optionalmarker[0] = undefined;
29339                    opts.optionalmarker[1] = undefined;
29340                }
29341                while (match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask)) {
29342                    m = match[0];
29343                    if (regexMask) {
29344                        switch (m.charAt(0)) {
29345                          case "?":
29346                            m = "{0,1}";
29347                            break;
29348
29349                          case "+":
29350                          case "*":
29351                            m = "{" + m + "}";
29352                            break;
29353                        }
29354                    }
29355                    if (escaped) {
29356                        defaultCase();
29357                        continue;
29358                    }
29359                    switch (m.charAt(0)) {
29360                      case "(?=":
29361                        break;
29362
29363                      case "(?!":
29364                        break;
29365
29366                      case "(?<=":
29367                        break;
29368
29369                      case "(?<!":
29370                        break;
29371
29372                      case opts.escapeChar:
29373                        escaped = true;
29374                        if (regexMask) {
29375                            defaultCase();
29376                        }
29377                        break;
29378
29379                      case opts.optionalmarker[1]:
29380                      case opts.groupmarker[1]:
29381                        openingToken = openenings.pop();
29382                        openingToken.openGroup = false;
29383                        if (openingToken !== undefined) {
29384                            if (openenings.length > 0) {
29385                                currentOpeningToken = openenings[openenings.length - 1];
29386                                currentOpeningToken.matches.push(openingToken);
29387                                if (currentOpeningToken.isAlternator) {
29388                                    alternator = openenings.pop();
29389                                    for (var mndx = 0; mndx < alternator.matches.length; mndx++) {
29390                                        alternator.matches[mndx].isGroup = false;
29391                                        alternator.matches[mndx].alternatorGroup = false;
29392                                    }
29393                                    if (openenings.length > 0) {
29394                                        currentOpeningToken = openenings[openenings.length - 1];
29395                                        currentOpeningToken.matches.push(alternator);
29396                                    } else {
29397                                        currentToken.matches.push(alternator);
29398                                    }
29399                                }
29400                            } else {
29401                                currentToken.matches.push(openingToken);
29402                            }
29403                        } else defaultCase();
29404                        break;
29405
29406                      case opts.optionalmarker[0]:
29407                        openenings.push(new MaskToken(false, true));
29408                        break;
29409
29410                      case opts.groupmarker[0]:
29411                        openenings.push(new MaskToken(true));
29412                        break;
29413
29414                      case opts.quantifiermarker[0]:
29415                        var quantifier = new MaskToken(false, false, true);
29416                        m = m.replace(/[{}]/g, "");
29417                        var mqj = m.split("|"), mq = mqj[0].split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = mq.length === 1 ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
29418                        if (mq0 === "*" || mq0 === "+") {
29419                            mq0 = mq1 === "*" ? 0 : 1;
29420                        }
29421                        quantifier.quantifier = {
29422                            min: mq0,
29423                            max: mq1,
29424                            jit: mqj[1]
29425                        };
29426                        var matches = openenings.length > 0 ? openenings[openenings.length - 1].matches : currentToken.matches;
29427                        match = matches.pop();
29428                        if (match.isAlternator) {
29429                            matches.push(match);
29430                            matches = match.matches;
29431                            var groupToken = new MaskToken(true);
29432                            var tmpMatch = matches.pop();
29433                            matches.push(groupToken);
29434                            matches = groupToken.matches;
29435                            match = tmpMatch;
29436                        }
29437                        if (!match.isGroup) {
29438                            match = groupify([ match ]);
29439                        }
29440                        matches.push(match);
29441                        matches.push(quantifier);
29442                        break;
29443
29444                      case opts.alternatormarker:
29445                        var groupQuantifier = function groupQuantifier(matches) {
29446                            var lastMatch = matches.pop();
29447                            if (lastMatch.isQuantifier) {
29448                                lastMatch = groupify([ matches.pop(), lastMatch ]);
29449                            }
29450                            return lastMatch;
29451                        };
29452                        if (openenings.length > 0) {
29453                            currentOpeningToken = openenings[openenings.length - 1];
29454                            var subToken = currentOpeningToken.matches[currentOpeningToken.matches.length - 1];
29455                            if (currentOpeningToken.openGroup && (subToken.matches === undefined || subToken.isGroup === false && subToken.isAlternator === false)) {
29456                                lastMatch = openenings.pop();
29457                            } else {
29458                                lastMatch = groupQuantifier(currentOpeningToken.matches);
29459                            }
29460                        } else {
29461                            lastMatch = groupQuantifier(currentToken.matches);
29462                        }
29463                        if (lastMatch.isAlternator) {
29464                            openenings.push(lastMatch);
29465                        } else {
29466                            if (lastMatch.alternatorGroup) {
29467                                alternator = openenings.pop();
29468                                lastMatch.alternatorGroup = false;
29469                            } else {
29470                                alternator = new MaskToken(false, false, false, true);
29471                            }
29472                            alternator.matches.push(lastMatch);
29473                            openenings.push(alternator);
29474                            if (lastMatch.openGroup) {
29475                                lastMatch.openGroup = false;
29476                                var alternatorGroup = new MaskToken(true);
29477                                alternatorGroup.alternatorGroup = true;
29478                                openenings.push(alternatorGroup);
29479                            }
29480                        }
29481                        break;
29482
29483                      default:
29484                        defaultCase();
29485                    }
29486                }
29487                while (openenings.length > 0) {
29488                    openingToken = openenings.pop();
29489                    currentToken.matches.push(openingToken);
29490                }
29491                if (currentToken.matches.length > 0) {
29492                    verifyGroupMarker(currentToken);
29493                    maskTokens.push(currentToken);
29494                }
29495                if (opts.numericInput || opts.isRTL) {
29496                    reverseTokens(maskTokens[0]);
29497                }
29498                return maskTokens;
29499            },
29500            positionColorMask: function positionColorMask(input, template) {
29501                input.style.left = template.offsetLeft + "px";
29502            }
29503        };
29504        Inputmask.extendDefaults = function(options) {
29505            $.extend(true, Inputmask.prototype.defaults, options);
29506        };
29507        Inputmask.extendDefinitions = function(definition) {
29508            $.extend(true, Inputmask.prototype.definitions, definition);
29509        };
29510        Inputmask.extendAliases = function(alias) {
29511            $.extend(true, Inputmask.prototype.aliases, alias);
29512        };
29513        Inputmask.format = function(value, options, metadata) {
29514            return Inputmask(options).format(value, metadata);
29515        };
29516        Inputmask.unmask = function(value, options) {
29517            return Inputmask(options).unmaskedvalue(value);
29518        };
29519        Inputmask.isValid = function(value, options) {
29520            return Inputmask(options).isValid(value);
29521        };
29522        Inputmask.remove = function(elems) {
29523            if (typeof elems === "string") {
29524                elems = document.getElementById(elems) || document.querySelectorAll(elems);
29525            }
29526            elems = elems.nodeName ? [ elems ] : elems;
29527            $.each(elems, function(ndx, el) {
29528                if (el.inputmask) el.inputmask.remove();
29529            });
29530        };
29531        Inputmask.setValue = function(elems, value) {
29532            if (typeof elems === "string") {
29533                elems = document.getElementById(elems) || document.querySelectorAll(elems);
29534            }
29535            elems = elems.nodeName ? [ elems ] : elems;
29536            $.each(elems, function(ndx, el) {
29537                if (el.inputmask) el.inputmask.setValue(value); else $(el).trigger("setvalue", [ value ]);
29538            });
29539        };
29540        Inputmask.escapeRegex = function(str) {
29541            var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ];
29542            return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1");
29543        };
29544        Inputmask.keyCode = {
29545            BACKSPACE: 8,
29546            BACKSPACE_SAFARI: 127,
29547            DELETE: 46,
29548            DOWN: 40,
29549            END: 35,
29550            ENTER: 13,
29551            ESCAPE: 27,
29552            HOME: 36,
29553            INSERT: 45,
29554            LEFT: 37,
29555            PAGE_DOWN: 34,
29556            PAGE_UP: 33,
29557            RIGHT: 39,
29558            SPACE: 32,
29559            TAB: 9,
29560            UP: 38,
29561            X: 88,
29562            CONTROL: 17
29563        };
29564        Inputmask.dependencyLib = $;
29565        function resolveAlias(aliasStr, options, opts) {
29566            var aliasDefinition = Inputmask.prototype.aliases[aliasStr];
29567            if (aliasDefinition) {
29568                if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias, undefined, opts);
29569                $.extend(true, opts, aliasDefinition);
29570                $.extend(true, opts, options);
29571                return true;
29572            } else if (opts.mask === null) {
29573                opts.mask = aliasStr;
29574            }
29575            return false;
29576        }
29577        function generateMaskSet(opts, nocache) {
29578            function generateMask(mask, metadata, opts) {
29579                var regexMask = false;
29580                if (mask === null || mask === "") {
29581                    regexMask = opts.regex !== null;
29582                    if (regexMask) {
29583                        mask = opts.regex;
29584                        mask = mask.replace(/^(\^)(.*)(\$)$/, "$2");
29585                    } else {
29586                        regexMask = true;
29587                        mask = ".*";
29588                    }
29589                }
29590                if (mask.length === 1 && opts.greedy === false && opts.repeat !== 0) {
29591                    opts.placeholder = "";
29592                }
29593                if (opts.repeat > 0 || opts.repeat === "*" || opts.repeat === "+") {
29594                    var repeatStart = opts.repeat === "*" ? 0 : opts.repeat === "+" ? 1 : opts.repeat;
29595                    mask = opts.groupmarker[0] + mask + opts.groupmarker[1] + opts.quantifiermarker[0] + repeatStart + "," + opts.repeat + opts.quantifiermarker[1];
29596                }
29597                var masksetDefinition, maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask;
29598                if (Inputmask.prototype.masksCache[maskdefKey] === undefined || nocache === true) {
29599                    masksetDefinition = {
29600                        mask: mask,
29601                        maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts),
29602                        validPositions: {},
29603                        _buffer: undefined,
29604                        buffer: undefined,
29605                        tests: {},
29606                        excludes: {},
29607                        metadata: metadata,
29608                        maskLength: undefined,
29609                        jitOffset: {}
29610                    };
29611                    if (nocache !== true) {
29612                        Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition;
29613                        masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]);
29614                    }
29615                } else masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]);
29616                return masksetDefinition;
29617            }
29618            var ms;
29619            if ($.isFunction(opts.mask)) {
29620                opts.mask = opts.mask(opts);
29621            }
29622            if ($.isArray(opts.mask)) {
29623                if (opts.mask.length > 1) {
29624                    if (opts.keepStatic === null) {
29625                        opts.keepStatic = "auto";
29626                        for (var i = 0; i < opts.mask.length; i++) {
29627                            if (opts.mask[i].charAt(0) !== opts.mask[0].charAt(0)) {
29628                                opts.keepStatic = true;
29629                                break;
29630                            }
29631                        }
29632                    }
29633                    var altMask = opts.groupmarker[0];
29634                    $.each(opts.isRTL ? opts.mask.reverse() : opts.mask, function(ndx, msk) {
29635                        if (altMask.length > 1) {
29636                            altMask += opts.groupmarker[1] + opts.alternatormarker + opts.groupmarker[0];
29637                        }
29638                        if (msk.mask !== undefined && !$.isFunction(msk.mask)) {
29639                            altMask += msk.mask;
29640                        } else {
29641                            altMask += msk;
29642                        }
29643                    });
29644                    altMask += opts.groupmarker[1];
29645                    return generateMask(altMask, opts.mask, opts);
29646                } else opts.mask = opts.mask.pop();
29647            }
29648            if (opts.mask && opts.mask.mask !== undefined && !$.isFunction(opts.mask.mask)) {
29649                ms = generateMask(opts.mask.mask, opts.mask, opts);
29650            } else {
29651                ms = generateMask(opts.mask, opts.mask, opts);
29652            }
29653            return ms;
29654        }
29655        function isInputEventSupported(eventName) {
29656            var el = document.createElement("input"), evName = "on" + eventName, isSupported = evName in el;
29657            if (!isSupported) {
29658                el.setAttribute(evName, "return;");
29659                isSupported = typeof el[evName] === "function";
29660            }
29661            el = null;
29662            return isSupported;
29663        }
29664        function maskScope(actionObj, maskset, opts) {
29665            maskset = maskset || this.maskset;
29666            opts = opts || this.opts;
29667            var inputmask = this, el = this.el, isRTL = this.isRTL, undoValue, $el, skipKeyPressEvent = false, skipInputEvent = false, ignorable = false, maxLength, mouseEnter = false, colorMask, originalPlaceholder;
29668            var getMaskTemplate = function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) {
29669                var greedy = opts.greedy;
29670                if (clearOptionalTail) opts.greedy = false;
29671                minimalPos = minimalPos || 0;
29672                var maskTemplate = [], ndxIntlzr, pos = 0, test, testPos, lvp = getLastValidPosition();
29673                do {
29674                    if (baseOnInput === true && getMaskSet().validPositions[pos]) {
29675                        testPos = clearOptionalTail && getMaskSet().validPositions[pos].match.optionality === true && getMaskSet().validPositions[pos + 1] === undefined && (getMaskSet().validPositions[pos].generatedInput === true || getMaskSet().validPositions[pos].input == opts.skipOptionalPartCharacter && pos > 0) ? determineTestTemplate(pos, getTests(pos, ndxIntlzr, pos - 1)) : getMaskSet().validPositions[pos];
29676                        test = testPos.match;
29677                        ndxIntlzr = testPos.locator.slice();
29678                        maskTemplate.push(includeMode === true ? testPos.input : includeMode === false ? test.nativeDef : getPlaceholder(pos, test));
29679                    } else {
29680                        testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
29681                        test = testPos.match;
29682                        ndxIntlzr = testPos.locator.slice();
29683                        var jitMasking = noJit === true ? false : opts.jitMasking !== false ? opts.jitMasking : test.jit;
29684                        if (jitMasking === false || jitMasking === undefined || typeof jitMasking === "number" && isFinite(jitMasking) && jitMasking > pos) {
29685                            maskTemplate.push(includeMode === false ? test.nativeDef : getPlaceholder(pos, test));
29686                        }
29687                    }
29688                    if (opts.keepStatic === "auto") {
29689                        if (test.newBlockMarker && test.fn !== null) {
29690                            opts.keepStatic = pos - 1;
29691                        }
29692                    }
29693                    pos++;
29694                } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || minimalPos > pos);
29695                if (maskTemplate[maskTemplate.length - 1] === "") {
29696                    maskTemplate.pop();
29697                }
29698                if (includeMode !== false || getMaskSet().maskLength === undefined) getMaskSet().maskLength = pos - 1;
29699                opts.greedy = greedy;
29700                return maskTemplate;
29701            };
29702            function getMaskSet() {
29703                return maskset;
29704            }
29705            function resetMaskSet(soft) {
29706                var maskset = getMaskSet();
29707                maskset.buffer = undefined;
29708                if (soft !== true) {
29709                    maskset.validPositions = {};
29710                    maskset.p = 0;
29711                }
29712            }
29713            function getLastValidPosition(closestTo, strict, validPositions) {
29714                var before = -1, after = -1, valids = validPositions || getMaskSet().validPositions;
29715                if (closestTo === undefined) closestTo = -1;
29716                for (var posNdx in valids) {
29717                    var psNdx = parseInt(posNdx);
29718                    if (valids[psNdx] && (strict || valids[psNdx].generatedInput !== true)) {
29719                        if (psNdx <= closestTo) before = psNdx;
29720                        if (psNdx >= closestTo) after = psNdx;
29721                    }
29722                }
29723                return before === -1 || before == closestTo ? after : after == -1 ? before : closestTo - before < after - closestTo ? before : after;
29724            }
29725            function getDecisionTaker(tst) {
29726                var decisionTaker = tst.locator[tst.alternation];
29727                if (typeof decisionTaker == "string" && decisionTaker.length > 0) {
29728                    decisionTaker = decisionTaker.split(",")[0];
29729                }
29730                return decisionTaker !== undefined ? decisionTaker.toString() : "";
29731            }
29732            function getLocator(tst, align) {
29733                var locator = (tst.alternation != undefined ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join("");
29734                if (locator !== "") while (locator.length < align) {
29735                    locator += "0";
29736                }
29737                return locator;
29738            }
29739            function determineTestTemplate(pos, tests) {
29740                pos = pos > 0 ? pos - 1 : 0;
29741                var altTest = getTest(pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch;
29742                for (var ndx = 0; ndx < tests.length; ndx++) {
29743                    var tst = tests[ndx];
29744                    tstLocator = getLocator(tst, targetLocator.length);
29745                    var distance = Math.abs(tstLocator - targetLocator);
29746                    if (closest === undefined || tstLocator !== "" && distance < closest || bestMatch && !opts.greedy && bestMatch.match.optionality && bestMatch.match.newBlockMarker === "master" && (!tst.match.optionality || !tst.match.newBlockMarker) || bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier) {
29747                        closest = distance;
29748                        bestMatch = tst;
29749                    }
29750                }
29751                return bestMatch;
29752            }
29753            function getTestTemplate(pos, ndxIntlzr, tstPs) {
29754                return getMaskSet().validPositions[pos] || determineTestTemplate(pos, getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs));
29755            }
29756            function getTest(pos, tests) {
29757                if (getMaskSet().validPositions[pos]) {
29758                    return getMaskSet().validPositions[pos];
29759                }
29760                return (tests || getTests(pos))[0];
29761            }
29762            function positionCanMatchDefinition(pos, def) {
29763                var valid = false, tests = getTests(pos);
29764                for (var tndx = 0; tndx < tests.length; tndx++) {
29765                    if (tests[tndx].match && tests[tndx].match.def === def) {
29766                        valid = true;
29767                        break;
29768                    }
29769                }
29770                return valid;
29771            }
29772            function getTests(pos, ndxIntlzr, tstPs) {
29773                var maskTokens = getMaskSet().maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = false, latestMatch, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : "";
29774                function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
29775                    function handleMatch(match, loopNdx, quantifierRecurse) {
29776                        function isFirstMatch(latestMatch, tokenGroup) {
29777                            var firstMatch = $.inArray(latestMatch, tokenGroup.matches) === 0;
29778                            if (!firstMatch) {
29779                                $.each(tokenGroup.matches, function(ndx, match) {
29780                                    if (match.isQuantifier === true) firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]); else if (match.hasOwnProperty("matches")) firstMatch = isFirstMatch(latestMatch, match);
29781                                    if (firstMatch) return false;
29782                                });
29783                            }
29784                            return firstMatch;
29785                        }
29786                        function resolveNdxInitializer(pos, alternateNdx, targetAlternation) {
29787                            var bestMatch, indexPos;
29788                            if (getMaskSet().tests[pos] || getMaskSet().validPositions[pos]) {
29789                                $.each(getMaskSet().tests[pos] || [ getMaskSet().validPositions[pos] ], function(ndx, lmnt) {
29790                                    if (lmnt.mloc[alternateNdx]) {
29791                                        bestMatch = lmnt;
29792                                        return false;
29793                                    }
29794                                    var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation, ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1;
29795                                    if ((indexPos === undefined || ndxPos < indexPos) && ndxPos !== -1) {
29796                                        bestMatch = lmnt;
29797                                        indexPos = ndxPos;
29798                                    }
29799                                });
29800                            }
29801                            if (bestMatch) {
29802                                var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation];
29803                                var locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator;
29804                                return locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1);
29805                            } else {
29806                                return targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined;
29807                            }
29808                        }
29809                        function isSubsetOf(source, target) {
29810                            function expand(pattern) {
29811                                var expanded = [], start, end;
29812                                for (var i = 0, l = pattern.length; i < l; i++) {
29813                                    if (pattern.charAt(i) === "-") {
29814                                        end = pattern.charCodeAt(i + 1);
29815                                        while (++start < end) {
29816                                            expanded.push(String.fromCharCode(start));
29817                                        }
29818                                    } else {
29819                                        start = pattern.charCodeAt(i);
29820                                        expanded.push(pattern.charAt(i));
29821                                    }
29822                                }
29823                                return expanded.join("");
29824                            }
29825                            if (opts.regex && source.match.fn !== null && target.match.fn !== null) {
29826                                return expand(target.match.def.replace(/[\[\]]/g, "")).indexOf(expand(source.match.def.replace(/[\[\]]/g, ""))) !== -1;
29827                            }
29828                            return source.match.def === target.match.nativeDef;
29829                        }
29830                        function staticCanMatchDefinition(source, target) {
29831                            var sloc = source.locator.slice(source.alternation).join(""), tloc = target.locator.slice(target.alternation).join(""), canMatch = sloc == tloc;
29832                            canMatch = canMatch && source.match.fn === null && target.match.fn !== null ? target.match.fn.test(source.match.def, getMaskSet(), pos, false, opts, false) : false;
29833                            return canMatch;
29834                        }
29835                        function setMergeLocators(targetMatch, altMatch) {
29836                            if (altMatch === undefined || targetMatch.alternation === altMatch.alternation && targetMatch.locator[targetMatch.alternation].toString().indexOf(altMatch.locator[altMatch.alternation]) === -1) {
29837                                targetMatch.mloc = targetMatch.mloc || {};
29838                                var locNdx = targetMatch.locator[targetMatch.alternation];
29839                                if (locNdx === undefined) targetMatch.alternation = undefined; else {
29840                                    if (typeof locNdx === "string") locNdx = locNdx.split(",")[0];
29841                                    if (targetMatch.mloc[locNdx] === undefined) targetMatch.mloc[locNdx] = targetMatch.locator.slice();
29842                                    if (altMatch !== undefined) {
29843                                        for (var ndx in altMatch.mloc) {
29844                                            if (typeof ndx === "string") ndx = ndx.split(",")[0];
29845                                            if (targetMatch.mloc[ndx] === undefined) targetMatch.mloc[ndx] = altMatch.mloc[ndx];
29846                                        }
29847                                        targetMatch.locator[targetMatch.alternation] = Object.keys(targetMatch.mloc).join(",");
29848                                    }
29849                                    return true;
29850                                }
29851                            }
29852                            return false;
29853                        }
29854                        if (testPos > 500 && quantifierRecurse !== undefined) {
29855                            throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + getMaskSet().mask;
29856                        }
29857                        if (testPos === pos && match.matches === undefined) {
29858                            matches.push({
29859                                match: match,
29860                                locator: loopNdx.reverse(),
29861                                cd: cacheDependency,
29862                                mloc: {}
29863                            });
29864                            return true;
29865                        } else if (match.matches !== undefined) {
29866                            if (match.isGroup && quantifierRecurse !== match) {
29867                                match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx, quantifierRecurse);
29868                                if (match) return true;
29869                            } else if (match.isOptional) {
29870                                var optionalToken = match;
29871                                match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
29872                                if (match) {
29873                                    $.each(matches, function(ndx, mtch) {
29874                                        mtch.match.optionality = true;
29875                                    });
29876                                    latestMatch = matches[matches.length - 1].match;
29877                                    if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) {
29878                                        insertStop = true;
29879                                        testPos = pos;
29880                                    } else return true;
29881                                }
29882                            } else if (match.isAlternator) {
29883                                var alternateToken = match, malternateMatches = [], maltMatches, currentMatches = matches.slice(), loopNdxCnt = loopNdx.length;
29884                                var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
29885                                if (altIndex === -1 || typeof altIndex === "string") {
29886                                    var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [], amndx;
29887                                    if (typeof altIndex == "string") {
29888                                        altIndexArr = altIndex.split(",");
29889                                    } else {
29890                                        for (amndx = 0;
29890 amndx < alternateToken.matches.length; amndx++) {
29891                                            altIndexArr.push(amndx.toString());
29892                                        }
29893                                    }
29894                                    if (getMaskSet().excludes[pos]) {
29895                                        var altIndexArrClone = altIndexArr.slice();
29896                                        for (var i = 0, el = getMaskSet().excludes[pos].length; i < el; i++) {
29897                                            altIndexArr.splice(altIndexArr.indexOf(getMaskSet().excludes[pos][i].toString()), 1);
29898                                        }
29899                                        if (altIndexArr.length === 0) {
29900                                            getMaskSet().excludes[pos] = undefined;
29901                                            altIndexArr = altIndexArrClone;
29902                                        }
29903                                    }
29904                                    if (opts.keepStatic === true || isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic) altIndexArr = altIndexArr.slice(0, 1);
29905                                    var unMatchedAlternation = false;
29906                                    for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
29907                                        amndx = parseInt(altIndexArr[ndx]);
29908                                        matches = [];
29909                                        ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice();
29910                                        if (alternateToken.matches[amndx] && handleMatch(alternateToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse)) match = true; else if (ndx === 0) {
29911                                            unMatchedAlternation = true;
29912                                        }
29913                                        maltMatches = matches.slice();
29914                                        testPos = currentPos;
29915                                        matches = [];
29916                                        for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
29917                                            var altMatch = maltMatches[ndx1], dropMatch = false;
29918                                            altMatch.match.jit = altMatch.match.jit || unMatchedAlternation;
29919                                            altMatch.alternation = altMatch.alternation || loopNdxCnt;
29920                                            setMergeLocators(altMatch);
29921                                            for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
29922                                                var altMatch2 = malternateMatches[ndx2];
29923                                                if (typeof altIndex !== "string" || altMatch.alternation !== undefined && $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr) !== -1) {
29924                                                    if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
29925                                                        dropMatch = true;
29926                                                        setMergeLocators(altMatch2, altMatch);
29927                                                        break;
29928                                                    } else if (isSubsetOf(altMatch, altMatch2)) {
29929                                                        if (setMergeLocators(altMatch, altMatch2)) {
29930                                                            dropMatch = true;
29931                                                            malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
29932                                                        }
29933                                                        break;
29934                                                    } else if (isSubsetOf(altMatch2, altMatch)) {
29935                                                        setMergeLocators(altMatch2, altMatch);
29936                                                        break;
29937                                                    } else if (staticCanMatchDefinition(altMatch, altMatch2)) {
29938                                                        if (setMergeLocators(altMatch, altMatch2)) {
29939                                                            dropMatch = true;
29940                                                            malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
29941                                                        }
29942                                                        break;
29943                                                    }
29944                                                }
29945                                            }
29946                                            if (!dropMatch) {
29947                                                malternateMatches.push(altMatch);
29948                                            }
29949                                        }
29950                                    }
29951                                    matches = currentMatches.concat(malternateMatches);
29952                                    testPos = pos;
29953                                    insertStop = matches.length > 0;
29954                                    match = malternateMatches.length > 0;
29955                                    ndxInitializer = ndxInitializerClone.slice();
29956                                } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse);
29957                                if (match) return true;
29958                            } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) {
29959                                var qt = match;
29960                                for (var qndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && testPos <= pos; qndx++) {
29961                                    var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1];
29962                                    match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup);
29963                                    if (match) {
29964                                        latestMatch = matches[matches.length - 1].match;
29965                                        latestMatch.optionalQuantifier = qndx >= qt.quantifier.min;
29966                                        latestMatch.jit = (qndx || 1) * tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit;
29967                                        if (latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
29968                                            insertStop = true;
29969                                            testPos = pos;
29970                                            break;
29971                                        }
29972                                        if (latestMatch.jit) {
29973                                            getMaskSet().jitOffset[pos] = tokenGroup.matches.indexOf(latestMatch);
29974                                        }
29975                                        return true;
29976                                    }
29977                                }
29978                            } else {
29979                                match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
29980                                if (match) return true;
29981                            }
29982                        } else {
29983                            testPos++;
29984                        }
29985                    }
29986                    for (var tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) {
29987                        if (maskToken.matches[tndx].isQuantifier !== true) {
29988                            var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
29989                            if (match && testPos === pos) {
29990                                return match;
29991                            } else if (testPos > pos) {
29992                                break;
29993                            }
29994                        }
29995                    }
29996                }
29997                function mergeLocators(pos, tests) {
29998                    var locator = [];
29999                    if (!$.isArray(tests)) tests = [ tests ];
30000                    if (tests.length > 0) {
30001                        if (tests[0].alternation === undefined) {
30002                            locator = determineTestTemplate(pos, tests.slice()).locator.slice();
30003                            if (locator.length === 0) locator = tests[0].locator.slice();
30004                        } else {
30005                            $.each(tests, function(ndx, tst) {
30006                                if (tst.def !== "") {
30007                                    if (locator.length === 0) locator = t
30007st.locator.slice(); else {
30008                                        for (var i = 0; i < locator.length; i++) {
30009                                            if (tst.locator[i] && locator[i].toString().indexOf(tst.locator[i]) === -1) {
30010                                                locator[i] += "," + tst.locator[i];
30011                                            }
30012                                        }
30013                                    }
30014                                }
30015                            });
30016                        }
30017                    }
30018                    return locator;
30019                }
30020                if (pos > -1) {
30021                    if (ndxIntlzr === undefined) {
30022                        var previousPos = pos - 1, test;
30023                        while ((test = getMaskSet().validPositions[previousPos] || getMaskSet().tests[previousPos]) === undefined && previousPos > -1) {
30024                            previousPos--;
30025                        }
30026                        if (test !== undefined && previousPos > -1) {
30027                            ndxInitializer = mergeLocators(previousPos, test);
30028                            cacheDependency = ndxInitializer.join("");
30029                            testPos = previousPos;
30030                        }
30031                    }
30032                    if (getMaskSet().tests[pos] && getMaskSet().tests[pos][0].cd === cacheDependency) {
30033                        return getMaskSet().tests[pos];
30034                    }
30035                    for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
30036                        var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]);
30037                        if (match && testPos === pos || testPos > pos) {
30038                            break;
30039                        }
30040                    }
30041                }
30042                if (matches.length === 0 || insertStop) {
30043                    matches.push({
30044                        match: {
30045                            fn: null,
30046                            optionality: false,
30047                            casing: null,
30048                            def: "",
30049                            placeholder: ""
30050                        },
30051                        locator: [],
30052                        mloc: {},
30053                        cd: cacheDependency
30054                    });
30055                }
30056                if (ndxIntlzr !== undefined && getMaskSet().tests[pos]) {
30057                    return $.extend(true, [], matches);
30058                }
30059                getMaskSet().tests[pos] = $.extend(true, [], matches);
30060                return getMaskSet().tests[pos];
30061            }
30062            function getBufferTemplate() {
30063                if (getMaskSet()._buffer === undefined) {
30064                    getMaskSet()._buffer = getMaskTemplate(false, 1);
30065                    if (getMaskSet().buffer === undefined) getMaskSet().buffer = getMaskSet()._buffer.slice();
30066                }
30067                return getMaskSet()._buffer;
30068            }
30069            function getBuffer(noCache) {
30070                if (getMaskSet().buffer === undefined || noCache === true) {
30071                    getMaskSet().buffer = getMaskTemplate(true, getLastValidPosition(), true);
30072                    if (getMaskSet()._buffer === undefined) getMaskSet()._buffer = getMaskSet().buffer.slice();
30073                }
30074                return getMaskSet().buffer;
30075            }
30076            function refreshFromBuffer(start, end, buffer) {
30077                var i, p;
30078                if (start === true) {
30079                    resetMaskSet();
30080                    start = 0;
30081                    end = buffer.length;
30082                } else {
30083                    for (i = start; i < end; i++) {
30084                        delete getMaskSet().validPositions[i];
30085                    }
30086                }
30087                p = start;
30088                for (i = start; i < end; i++) {
30089                    resetMaskSet(true);
30090                    if (buffer[i] !== opts.skipOptionalPartCharacter) {
30091                        var valResult = isValid(p, buffer[i], true, true);
30092                        if (valResult !== false) {
30093                            resetMaskSet(true);
30094                            p = valResult.caret !== undefined ? valResult.caret : valResult.pos + 1;
30095                        }
30096                    }
30097                }
30098            }
30099            function casing(elem, test, pos) {
30100                switch (opts.casing || test.casing) {
30101                  case "upper":
30102                    elem = elem.toUpperCase();
30103                    break;
30104
30105                  case "lower":
30106                    elem = elem.toLowerCase();
30107                    break;
30108
30109                  case "title":
30110                    var posBefore = getMaskSet().validPositions[pos - 1];
30111                    if (pos === 0 || posBefore && posBefore.input === String.fromCharCode(Inputmask.keyCode.SPACE)) {
30112                        elem = elem.toUpperCase();
30113                    } else {
30114                        elem = elem.toLowerCase();
30115                    }
30116                    break;
30117
30118                  default:
30119                    if ($.isFunction(opts.casing)) {
30120                        var args = Array.prototype.slice.call(arguments);
30121                        args.push(getMaskSet().validPositions);
30122                        elem = opts.casing.apply(this, args);
30123                    }
30124                }
30125                return elem;
30126            }
30127            function checkAlternationMatch(altArr1, altArr2, na) {
30128                var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = false, naArr = na !== undefined ? na.split(",") : [], naNdx;
30129                for (var i = 0; i < naArr.length; i++) {
30130                    if ((naNdx = altArr1.indexOf(naArr[i])) !== -1) {
30131                        altArr1.splice(naNdx, 1);
30132                    }
30133                }
30134                for (var alndx = 0; alndx < altArr1.length; alndx++) {
30135                    if ($.inArray(altArr1[alndx], altArrC) !== -1) {
30136                        isMatch = true;
30137                        break;
30138                    }
30139                }
30140                return isMatch;
30141            }
30142            function alternate(pos, c, strict, fromSetValid, rAltPos) {
30143                var validPsClone = $.extend(true, {}, getMaskSet().validPositions), lastAlt, alternation, isValidRslt = false, altPos, prevAltPos, i, validPos, decisionPos, lAltPos = rAltPos !== undefined ? rAltPos : getLastValidPosition();
30144                if (lAltPos === -1 && rAltPos === undefined) {
30145                    lastAlt = 0;
30146                    prevAltPos = getTest(lastAlt);
30147                    alternation = prevAltPos.alternation;
30148                } else {
30149                    for (;lAltPos >= 0; lAltPos--) {
30150                        altPos = getMaskSet().validPositions[lAltPos];
30151                        if (altPos && altPos.alternation !== undefined) {
30152                            if (prevAltPos && prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) {
30153                                break;
30154                            }
30155                            lastAlt = lAltPos;
30156                            alternation = getMaskSet().validPositions[lastAlt].alternation;
30157                            prevAltPos = altPos;
30158                        }
30159                    }
30160                }
30161                if (alternation !== undefined) {
30162                    decisionPos = parseInt(lastAlt);
30163                    getMaskSet().excludes[decisionPos] = getMaskSet().excludes[decisionPos] || [];
30164                    if (pos !== true) {
30165                        getMaskSet().excludes[decisionPos].push(getDecisionTaker(prevAltPos));
30166                    }
30167                    var validInputsClone = [], staticInputsBeforePos = 0;
30168                    for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) {
30169                        validPos = getMaskSet().validPositions[i];
30170                        if (validPos && validPos.generatedInput !== true) {
30171                            validInputsClone.push(validPos.input);
30172                        } else if (i < pos) staticInputsBeforePos++;
30173                        delete getMaskSet().validPositions[i];
30174                    }
30175                    while (getMaskSet().excludes[decisionPos] && getMaskSet().excludes[decisionPos].length < 10) {
30176                        var posOffset = staticInputsBeforePos * -1, validInputs = validInputsClone.slice();
30177                        getMaskSet().tests[decisionPos] = undefined;
30178                        resetMaskSet(true);
30179                        isValidRslt = true;
30180                        while (validInputs.length > 0) {
30181                            var input = validInputs.shift();
30182                            if (!(isValidRslt = isValid(getLastValidPosition(undefined, true) + 1, input, false, fromSetValid, true))) {
30183                                break;
30184                            }
30185                        }
30186                        if (isValidRslt && c !== undefined) {
30187                            var targetLvp = getLastValidPosition(pos) + 1;
30188                            for (i = decisionPos; i < getLastValidPosition() + 1; i++) {
30189                                validPos = getMaskSet().validPositions[i];
30190                                if ((validPos === undefined || validPos.match.fn == null) && i < pos + posOffset) {
30191                                    posOffset++;
30192                                }
30193                            }
30194                            pos = pos + posOffset;
30195                            isValidRslt = isValid(pos > targetLvp ? targetLvp : pos, c, strict, fromSetValid, true);
30196                        }
30197                        if (!isValidRslt) {
30198                            resetMaskSet();
30199                            prevAltPos = getTest(decisionPos);
30200                            getMaskSet().validPositions = $.extend(true, {}, validPsClone);
30201                            if (getMaskSet().excludes[decisionPos]) {
30202                                var decisionTaker = getDecisionTaker(prevAltPos);
30203                                if (getMaskSet().excludes[decisionPos].indexOf(decisionTaker) !== -1) {
30204                                    isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1);
30205                                    break;
30206                                }
30207                                getMaskSet().excludes[decisionPos].push(decisionTaker);
30208                                for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) {
30209                                    delete getMaskSet().validPositions[i];
30210                                }
30211                            } else {
30212                                isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1);
30213                                break;
30214                            }
30215                        } else break;
30216                    }
30217                }
30218                getMaskSet().excludes[decisionPos] = undefined;
30219                return isValidRslt;
30220            }
30221            function isValid(pos, c, strict, fromSetValid, fromAlternate, validateOnly) {
30222                function isSelection(posObj) {
30223                    return isRTL ? posObj.begin - posObj.end > 1 || posObj.begin - posObj.end === 1 : posObj.end - posObj.begin > 1 || posObj.end - posObj.begin === 1;
30224                }
30225                strict = strict === true;
30226                var maskPos = pos;
30227                if (pos.begin !== undefined) {
30228                    maskPos = isRTL ? pos.end : pos.begin;
30229                }
30230                function _isValid(position, c, strict) {
30231                    var rslt = false;
30232                    $.each(getTests(position), function(ndx, tst) {
30233                        var test = tst.match;
30234                        getBuffer(true);
30235                        rslt = test.fn != null ? test.fn.test(c, getMaskSet(), position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && test.def !== "" ? {
30236                            c: getPlaceholder(position, test, true) || test.def,
30237                            pos: position
30238                        } : false;
30239                        if (rslt !== false) {
30240                            var elem = rslt.c !== undefined ? rslt.c : c, validatedPos = position;
30241                            elem = elem === opts.skipOptionalPartCharacter && test.fn === null ? getPlaceholder(position, test, true) || test.def : elem;
30242                            if (rslt.remove !== undefined) {
30243                                if (!$.isArray(rslt.remove)) rslt.remove = [ rslt.remove ];
30244                                $.each(rslt.remove.sort(function(a, b) {
30245                                    return b - a;
30246                                }), function(ndx, lmnt) {
30247                                    revalidateMask({
30248                                        begin: lmnt,
30249                                        end: lmnt + 1
30250                                    });
30251                                });
30252                            }
30253                            if (rslt.insert !== undefined) {
30254                                if (!$.isArray(rslt.insert)) rslt.insert = [ rslt.insert ];
30255                                $.each(rslt.insert.sort(function(a, b) {
30256                                    return a - b;
30257                                }), function(ndx, lmnt) {
30258                                    isValid(lmnt.pos, lmnt.c, true, fromSetValid);
30259                                });
30260                            }
30261                            if (rslt !== true && rslt.pos !== undefined && rslt.pos !== position) {
30262                                validatedPos = rslt.pos;
30263                            }
30264                            if (rslt !== true && rslt.pos === undefined && rslt.c === undefined) {
30265                                return false;
30266                            }
30267                            if (!revalidateMask(pos, $.extend({}, tst, {
30268                                input: casing(elem, test, validatedPos)
30269                            }), fromSetValid, validatedPos)) {
30270                                rslt = false;
30271                            }
30272                            return false;
30273                        }
30274                    });
30275                    return rslt;
30276                }
30277                var result = true, positionsClone = $.extend(true, {}, getMaskSet().validPositions);
30278                if ($.isFunction(opts.preValidation) && !strict && fromSetValid !== true && validateOnly !== true) {
30279                    result = opts.preValidation(getBuffer(), maskPos, c, isSelection(pos), opts, getMaskSet());
30280                }
30281                if (result === true) {
30282                    trackbackPositions(undefined, maskPos, true);
30283                    if (maxLength === undefined || maskPos < maxLength) {
30284                        result = _isValid(maskPos, c, strict);
30285                        if ((!strict || fromSetValid === true) && result === false && validateOnly !== true) {
30286                            var currentPosValid = getMaskSet().validPositions[maskPos];
30287                            if (currentPosValid && currentPosValid.match.fn === null && (currentPosValid.match.def === c || c === opts.skipOptionalPartCharacter)) {
30288                                result = {
30289                                    caret: seekNext(maskPos)
30290                                };
30291                            } else {
30292                                if ((opts.insertMode || getMaskSet().validPositions[seekNext(maskPos)] === undefined) && (!isMask(maskPos, true) || getMaskSet().jitOffset[maskPos])) {
30293                                    if (getMaskSet().jitOffset[maskPos] && getMaskSet().validPositions[seekNext(maskPos)] === undefined) {
30294                                        result = isValid(maskPos + getMaskSet().jitOffset[maskPos], c, strict);
30295                                        if (result !== false) result.caret = maskPos;
30296                                    } else for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) {
30297                                        result = _isValid(nPos, c, strict);
30298                                        if (result !== false) {
30299                                            result = trackbackPositions(maskPos, result.pos !== undefined ? result.pos : nPos) || result;
30300                                            maskPos = nPos;
30301                                            break;
30302                                        }
30303                                    }
30304                                }
30305                            }
30306                        }
30307                    }
30308                    if (result === false && opts.keepStatic !== false && (opts.regex == null || isComplete(getBuffer())) && !strict && fromAlternate !== true) {
30309                        result = alternate(maskPos, c, strict, fromSetValid);
30310                    }
30311                    if (result === true) {
30312                        result = {
30313                            pos: maskPos
30314                        };
30315                    }
30316                }
30317                if ($.isFunction(opts.postValidation) && result !== false && !strict && fromSetValid !== true && validateOnly !== true) {
30318                    var postResult = opts.postValidation(getBuffer(true), pos.begin !== undefined ? isRTL ? pos.end : pos.begin : pos, result, opts);
30319                    if (postResult !== undefined) {
30320                        if (postResult.refreshFromBuffer && postResult.buffer) {
30321                            var refresh = postResult.refreshFromBuffer;
30322                            refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, postResult.buffer);
30323                        }
30324                        result = postResult === true ? result : postResult;
30325                    }
30326                }
30327                if (result && result.pos === undefined) {
30328                    result.pos = maskPos;
30329                }
30330                if (result === false || validateOnly === true) {
30331                    resetMaskSet(true);
30332                    getMaskSet().validPositions = $.extend(true, {}, positionsClone);
30333                }
30334                return result;
30335            }
30336            function trackbackPositions(originalPos, newPos, fillOnly) {
30337                var result;
30338                if (originalPos === undefined) {
30339                    for (originalPos = newPos - 1; originalPos > 0; originalPos--) {
30340                        if (getMaskSet().validPositions[originalPos]) break;
30341                    }
30342                }
30343                for (var ps = originalPos; ps < newPos; ps++) {
30344                    if (getMaskSet().validPositions[ps] === undefined && !isMask(ps, true)) {
30345                        var vp = ps == 0 ? getTest(ps) : getMaskSet().validPositions[ps - 1];
30346                        if (vp) {
30347                            var tests = getTests(ps).slice();
30348                            if (tests[tests.length - 1].match.def === "") tests.pop();
30349                            var bestMatch = determineTestTemplate(ps, tests);
30350                            bestMatch = $.extend({}, bestMatch, {
30351                                input: getPlaceholder(ps, bestMatch.match, true) || bestMatch.match.def
30352                            });
30353                            bestMatch.generatedInput = true;
30354                            revalidateMask(ps, bestMatch, true);
30355                            if (fillOnly !== true) {
30356                                var cvpInput = getMaskSet().validPositions[newPos].input;
30357                                getMaskSet().validPositions[newPos] = undefined;
30358                                result = isValid(newPos, cvpInput, true, true);
30359                            }
30360                        }
30361                    }
30362                }
30363                return result;
30364            }
30365            function revalidateMask(pos, validTest, fromSetValid, validatedPos) {
30366                function IsEnclosedStatic(pos, valids, selection) {
30367                    var posMatch = valids[pos];
30368                    if (posMatch !== undefined && (posMatch.match.fn === null && posMatch.match.optionality !== true || posMatch.input === opts.radixPoint)) {
30369                        var prevMatch = selection.begin <= pos - 1 ? valids[pos - 1] && valids[pos - 1].match.fn === null && valids[pos - 1] : valids[pos - 1], nextMatch = selection.end > pos + 1 ? valids[pos + 1] && valids[pos + 1].match.fn === null && valids[pos + 1] : valids[pos + 1];
30370                        return prevMatch && nextMatch;
30371                    }
30372                    return false;
30373                }
30374                var begin = pos.begin !== undefined ? pos.begin : pos, end = pos.end !== undefined ? pos.end : pos;
30375                if (pos.begin > pos.end) {
30376                    begin = pos.end;
30377                    end = pos.begin;
30378                }
30379                validatedPos = validatedPos !== undefined ? validatedPos : begin;
30380                if (begin !== end || opts.insertMode && getMaskSet().validPositions[validatedPos] !== undefined && fromSetValid === undefined) {
30381                    var positionsClone = $.extend(true, {}, getMaskSet().validPositions), lvp = getLastValidPosition(undefined, true), i;
30382                    getMaskSet().p = begin;
30383                    for (i = lvp; i >= begin; i--) {
30384                        if (getMaskSet().validPositions[i] && getMaskSet().validPositions[i].match.nativeDef === "+") {
30385                            opts.isNegative = false;
30386                        }
30387                        delete getMaskSet().validPositions[i];
30388                    }
30389                    var valid = true, j = validatedPos, vps = getMaskSet().validPositions, needsValidation = false, posMatch = j, i = j;
30390                    if (validTest) {
30391                        getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest);
30392                        posMatch++;
30393                        j++;
30394                        if (begin < end) i++;
30395                    }
30396                    for (;i <= lvp; i++) {
30397                        var t = positionsClone[i];
30398                        if (t !== undefined && (i >= end || i >= begin && t.generatedInput !== true && IsEnclosedStatic(i, positionsClone, {
30399                            begin: begin,
30400                            end: end
30401                        }))) {
30402                            while (getTest(posMatch).match.def !== "") {
30403                                if (needsValidation === false && positionsClone[posMatch] && positionsClone[posMatch].match.nativeDef === t.match.nativeDef) {
30404                                    getMaskSet().validPositions[posMatch] = $.extend(true, {}, positionsClone[posMatch]);
30405                                    getMaskSet().validPositions[posMatch].input = t.input;
30406                                    trackbackPositions(undefined, posMatch, true);
30407                                    j = posMatch + 1;
30408                                    valid = true;
30409                                } else if (opts.shiftPositions && positionCanMatchDefinition(posMatch, t.match.def)) {
30410                                    var result = isValid(posMatch, t.input, true, true);
30411                                    valid = result !== false;
30412                                    j = result.caret || result.insert ? getLastValidPosition() : posMatch + 1;
30413                                    needsValidation = true;
30414                                } else {
30415                                    valid = t.generatedInput === true || t.input === opts.radixPoint && opts.numericInput === true;
30416                                }
30417                                if (valid) break;
30418                                if (!valid && posMatch > end && isMask(posMatch, true) && (t.match.fn !== null || posMatch > getMaskSet().maskLength)) {
30419                                    break;
30420                                }
30421                                posMatch++;
30422                            }
30423                            if (getTest(posMatch).match.def == "") valid = false;
30424                            posMatch = j;
30425                        }
30426                        if (!valid) break;
30427                    }
30428                    if (!valid) {
30429                        getMaskSet().validPositions = $.extend(true, {}, positionsClone);
30430                        resetMaskSet(true);
30431                        return false;
30432                    }
30433                } else if (validTest) {
30434                    getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest);
30435                }
30436                resetMaskSet(true);
30437                return true;
30438            }
30439            function isMask(pos, strict) {
30440                var test = getTestTemplate(pos).match;
30441                if (test.def === "") test = getTest(pos).match;
30442                if (test.fn != null) {
30443                    return test.fn;
30444                }
30445                if (strict !== true && pos > -1) {
30446                    var tests = getTests(pos);
30447                    return tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0);
30448                }
30449                return false;
30450            }
30451            function seekNext(pos, newBlock) {
30452                var position = pos + 1;
30453                while (getTest(position).match.def !== "" && (newBlock === true && (getTest(position).match.newBlockMarker !== true || !isMask(position)) || newBlock !== true && !isMask(position))) {
30454                    position++;
30455                }
30456                return position;
30457            }
30458            function seekPrevious(pos, newBlock) {
30459                var position = pos, tests;
30460                if (position <= 0) return 0;
30461                while (--position > 0 && (newBlock === true && getTest(position).match.newBlockMarker !== true || newBlock !== true && !isMask(position) && (tests = getTests(position), 
30462                tests.length < 2 || tests.length === 2 && tests[1].match.def === ""))) {}
30463                return position;
30464            }
30465            function writeBuffer(input, buffer, caretPos, event, triggerEvents) {
30466                if (event && $.isFunction(opts.onBeforeWrite)) {
30467                    var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts);
30468                    if (result) {
30469                        if (result.refreshFromBuffer) {
30470                            var refresh = result.refreshFromBuffer;
30471                            refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer);
30472                            buffer = getBuffer(true);
30473                        }
30474                        if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos;
30475                    }
30476                }
30477                if (input !== undefined) {
30478                    input.inputmask._valueSet(buffer.join(""));
30479                    if (caretPos !== undefined && (event === undefined || event.type !== "blur")) {
30480                        caret(input, caretPos);
30481                    } else renderColorMask(input, caretPos, buffer.length === 0);
30482                    if (triggerEvents === true) {
30483                        var $input = $(input), nptVal = input.inputmask._valueGet();
30484                        skipInputEvent = true;
30485                        $input.trigger("input");
30486                        setTimeout(function() {
30487                            if (nptVal === getBufferTemplate().join("")) {
30488                                $input.trigger("cleared");
30489                            } else if (isComplete(buffer) === true) {
30490                                $input.trigger("complete");
30491                            }
30492                        }, 0);
30493                    }
30494                }
30495            }
30496            function getPlaceholder(pos, test, returnPL) {
30497                test = test || getTest(pos).match;
30498                if (test.placeholder !== undefined || returnPL === true) {
30499                    return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder;
30500                } else if (test.fn === null) {
30501                    if (pos > -1 && getMaskSet().validPositions[pos] === undefined) {
30502                        var tests = getTests(pos), staticAlternations = [], prevTest;
30503                        if (tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0)) {
30504                            for (var i = 0; i < tests.length; i++) {
30505                                if (tests[i].match.optionality !== true && tests[i].match.optionalQuantifier !== true && (tests[i].match.fn === null || prevTest === undefined || tests[i].match.fn.test(prevTest.match.def, getMaskSet(), pos, true, opts) !== false)) {
30506                                    staticAlternations.push(tests[i]);
30507                                    if (tests[i].match.fn === null) prevTest = tests[i];
30508                                    if (staticAlternations.length > 1) {
30509                                        if (/[0-9a-bA-Z]/.test(staticAlternations[0].match.def)) {
30510                                            return opts.placeholder.charAt(pos % opts.placeholder.length);
30511                                        }
30512                                    }
30513                                }
30514                            }
30515                        }
30516                    }
30517                    return test.def;
30518                }
30519                return opts.placeholder.charAt(pos % opts.placeholder.length);
30520            }
30521            function HandleNativePlaceholder(npt, value) {
30522                if (ie) {
30523                    if (npt.inputmask._valueGet() !== value && (npt.placeholder !== value || npt.placeholder === "")) {
30524                        var buffer = getBuffer().slice(), nptValue = npt.inputmask._valueGet();
30525                        if (nptValue !== value) {
30526                            var lvp = getLastValidPosition();
30527                            if (lvp === -1 && nptValue === getBufferTemplate().join("")) {
30528                                buffer = [];
30529                            } else if (lvp !== -1) {
30530                                clearOptionalTail(buffer);
30531                            }
30532                            writeBuffer(npt, buffer);
30533                        }
30534                    }
30535                } else if (npt.placeholder !== value) {
30536                    npt.placeholder = value;
30537                    if (npt.placeholder === "") npt.removeAttribute("placeholder");
30538                }
30539            }
30540            var EventRuler = {
30541                on: function on(input, eventName, eventHandler) {
30542                    var ev = function ev(e) {
30543                        var that = this;
30544                        if (that.inputmask === undefined && this.nodeName !== "FORM") {
30545                            var imOpts = $.data(that, "_inputmask_opts");
30546                            if (imOpts) new Inputmask(imOpts).mask(that); else EventRuler.off(that);
30547                        } else if (e.type !== "setvalue" && this.nodeName !== "FORM" && (that.disabled || that.readOnly && !(e.type === "keydown" && e.ctrlKey && e.keyCode === 67 || opts.tabThrough === false && e.keyCode === Inputmask.keyCode.TAB))) {
30548                            e.preventDefault();
30549                        } else {
30550                            switch (e.type) {
30551                              case "input":
30552                                if (skipInputEvent === true) {
30553                                    skipInputEvent = false;
30554                                    return e.preventDefault();
30555                                }
30556                                if (mobile) {
30557                                    var args = arguments;
30558                                    setTimeout(function() {
30559                                        eventHandler.apply(that, args);
30560                                        caret(that, that.inputmask.caretPos, undefined, true);
30561                                    }, 0);
30562                                    return false;
30563                                }
30564                                break;
30565
30566                              case "keydown":
30567                                skipKeyPressEvent = false;
30568                                skipInputEvent = false;
30569                                break;
30570
30571                              case "keypress":
30572                                if (skipKeyPressEvent === true) {
30573                                    return e.preventDefault();
30574                                }
30575                                skipKeyPressEvent = true;
30576                                break;
30577
30578                              case "click":
30579                                if (iemobile || iphone) {
30580                                    var args = arguments;
30581                                    setTimeout(function() {
30582                                        eventHandler.apply(that, args);
30583                                    }, 0);
30584                                    return false;
30585                                }
30586                                break;
30587                            }
30588                            var returnVal = eventHandler.apply(that, arguments);
30589                            if (returnVal === false) {
30590                                e.preventDefault();
30591                                e.stopPropagation();
30592                            }
30593                            return returnVal;
30594                        }
30595                    };
30596                    input.inputmask.events[eventName] = input.inputmask.events[eventName] || [];
30597                    input.inputmask.events[eventName].push(ev);
30598                    if ($.inArray(eventName, [ "submit", "reset" ]) !== -1) {
30599                        if (input.form !== null) $(input.form).on(eventName, ev);
30600                    } else {
30601                        $(input).on(eventName, ev);
30602                    }
30603                },
30604                off: function off(input, event) {
30605                    if (input.inputmask && input.inputmask.events) {
30606                        var events;
30607                        if (event) {
30608                            events = [];
30609                            events[event] = input.inputmask.events[event];
30610                        } else {
30611                            events = input.inputmask.events;
30612                        }
30613                        $.each(events, function(eventName, evArr) {
30614                            while (evArr.length > 0) {
30615                                var ev = evArr.pop();
30616                                if ($.inArray(eventName, [ "submit", "reset" ]) !== -1) {
30617                                    if (input.form !== null) $(input.form).off(eventName, ev);
30618                                } else {
30619                                    $(input).off(eventName, ev);
30620                                }
30621                            }
30622                            delete input.inputmask.events[eventName];
30623                        });
30624                    }
30625                }
30626            };
30627            var EventHandlers = {
30628                keydownEvent: function keydownEvent(e) {
30629                    var input = this, $input = $(input), k = e.keyCode, pos = caret(input);
30630                    if (k === Inputmask.keyCode.BACKSPACE || k === Inputmask.keyCode.DELETE || iphone && k === Inputmask.keyCode.BACKSPACE_SAFARI || e.ctrlKey && k === Inputmask.keyCode.X && !isInputEventSupported("cut")) {
30631                        e.preventDefault();
30632                        handleRemove(input, k, pos);
30633                        writeBuffer(input, getBuffer(true), getMaskSet().p, e, input.inputmask._valueGet() !== getBuffer().join(""));
30634                    } else if (k === Inputmask.keyCode.END || k === Inputmask.keyCode.PAGE_DOWN) {
30635                        e.preventDefault();
30636                        var caretPos = seekNext(getLastValidPosition());
30637                        caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, true);
30638                    } else if (k === Inputmask.keyCode.HOME && !e.shiftKey || k === Inputmask.keyCode.PAGE_UP) {
30639                        e.preventDefault();
30640                        caret(input, 0, e.shiftKey ? pos.begin : 0, true);
30641                    } else if ((opts.undoOnEscape && k === Inputmask.keyCode.ESCAPE || k === 90 && e.ctrlKey) && e.altKey !== true) {
30642                        checkVal(input, true, false, undoValue.split(""));
30643                        $input.trigger("click");
30644                    } else if (k === Inputmask.keyCode.INSERT && !(e.shiftKey || e.ctrlKey)) {
30645                        opts.insertMode = !opts.insertMode;
30646                        input.setAttribute("im-insert", opts.insertMode);
30647                    } else if (opts.tabThrough === true && k === Inputmask.keyCode.TAB) {
30648                        if (e.shiftKey === true) {
30649                            if (getTest(pos.begin).match.fn === null) {
30650                                pos.begin = seekNext(pos.begin);
30651                            }
30652                            pos.end = seekPrevious(pos.begin, true);
30653                            pos.begin = seekPrevious(pos.end, true);
30654                        } else {
30655                            pos.begin = seekNext(pos.begin, true);
30656                            pos.end = seekNext(pos.begin, true);
30657                            if (pos.end < getMaskSet().maskLength) pos.end--;
30658                        }
30659                        if (pos.begin < getMaskSet().maskLength) {
30660                            e.preventDefault();
30661                            caret(input, pos.begin, pos.end);
30662                        }
30663                    }
30664                    opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts);
30665                    ignorable = $.inArray(k, opts.ignorables) !== -1;
30666                },
30667                keypressEvent: function keypressEvent(e, checkval, writeOut, strict, ndx) {
30668                    var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
30669                    if (checkval !== true && !(e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) {
30670                        if (k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("")) {
30671                            undoValue = getBuffer().join("");
30672                            setTimeout(function() {
30673                                $input.trigger("change");
30674                            }, 0);
30675                        }
30676                        return true;
30677                    } else {
30678                        if (k) {
30679                            if (k === 46 && e.shiftKey === false && opts.radixPoint !== "") k = opts.radixPoint.charCodeAt(0);
30680                            var pos = checkval ? {
30681                                begin: ndx,
30682                                end: ndx
30683                            } : caret(input), forwardPosition, c = String.fromCharCode(k), offset = 0;
30684                            if (opts._radixDance && opts.numericInput) {
30685                                var caretPos = getBuffer().indexOf(opts.radixPoint.charAt(0)) + 1;
30686                                if (pos.begin <= caretPos) {
30687                                    if (k === opts.radixPoint.charCodeAt(0)) offset = 1;
30688                                    pos.begin -= 1;
30689                                    pos.end -= 1;
30690                                }
30691                            }
30692                            getMaskSet().writeOutBuffer = true;
30693                            var valResult = isValid(pos, c, strict);
30694                            if (valResult !== false) {
30695                                resetMaskSet(true);
30696                                forwardPosition = valResult.caret !== undefined ? valResult.caret : seekNext(valResult.pos.begin ? valResult.pos.begin : valResult.pos);
30697                                getMaskSet().p = forwardPosition;
30698                            }
30699                            forwardPosition = (opts.numericInput && valResult.caret === undefined ? seekPrevious(forwardPosition) : forwardPosition) + offset;
30700                            if (writeOut !== false) {
30701                                setTimeout(function() {
30702                                    opts.onKeyValidation.call(input, k, valResult, opts);
30703                                }, 0);
30704                                if (getMaskSet().writeOutBuffer && valResult !== false) {
30705                                    var buffer = getBuffer();
30706                                    writeBuffer(input, buffer, forwardPosition, e, checkval !== true);
30707                                }
30708                            }
30709                            e.preventDefault();
30710                            if (checkval) {
30711                                if (valResult !== false) valResult.forwardPosition = forwardPosition;
30712                                return valResult;
30713                            }
30714                        }
30715                    }
30716                },
30717                pasteEvent: function pasteEvent(e) {
30718                    var input = this, ev = e.originalEvent || e, $input = $(input), inputValue = input.inputmask._valueGet(true), caretPos = caret(input), tempValue;
30719                    if (isRTL) {
30720                        tempValue = caretPos.end;
30721                        caretPos.end = caretPos.begin;
30722                        caretPos.begin = tempValue;
30723                    }
30724                    var valueBeforeCaret = inputValue.substr(0, caretPos.begin), valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);
30725                    if (valueBeforeCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(0, caretPos.begin).join("")) valueBeforeCaret = "";
30726                    if (valueAfterCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(caretPos.end).join("")) valueAfterCaret = "";
30727                    if (window.clipboardData && window.clipboardData.getData) {
30728                        inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret;
30729                    } else if (ev.clipboardData && ev.clipboardData.getData) {
30730                        inputValue = valueBeforeCaret + ev.clipboardData.getData("text/plain") + valueAfterCaret;
30731                    } else return true;
30732                    var pasteValue = inputValue;
30733                    if ($.isFunction(opts.onBeforePaste)) {
30734                        pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts);
30735                        if (pasteValue === false) {
30736                            return e.preventDefault();
30737                        }
30738                        if (!pasteValue) {
30739                            pasteValue = inputValue;
30740                        }
30741                    }
30742                    checkVal(input, false, false, pasteValue.toString().split(""));
30743                    writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join(""));
30744                    return e.preventDefault();
30745                },
30746                inputFallBackEvent: function inputFallBackEvent(e) {
30747                    function radixPointHandler(input, inputValue, caretPos) {
30748                        if (inputValue.charAt(caretPos.begin - 1) === "." && opts.radixPoint !== "") {
30749                            inputValue = inputValue.split("");
30750                            inputValue[caretPos.begin - 1] = opts.radixPoint.charAt(0);
30751                            inputValue = inputValue.join("");
30752                        }
30753                        return inputValue;
30754                    }
30755                    function ieMobileHandler(input, inputValue, caretPos) {
30756                        if (iemobile) {
30757                            var inputChar = inputValue.replace(getBuffer().join(""), "");
30758                            if (inputChar.length === 1) {
30759                                var iv = inputValue.split("");
30760                                iv.splice(caretPos.begin, 0, inputChar);
30761                                inputValue = iv.join("");
30762                            }
30763                        }
30764                        return inputValue;
30765                    }
30766                    var input = this, inputValue = input.inputmask._valueGet();
30767                    if (getBuffer().join("") !== inputValue) {
30768                        var caretPos = caret(input);
30769                        inputValue = radixPointHandler(input, inputValue, caretPos);
30770                        inputValue = ieMobileHandler(input, inputValue, caretPos);
30771                        if (getBuffer().join("") !== inputValue) {
30772                            var buffer = getBuffer().join(""), offset = !opts.numericInput && inputValue.length > buffer.length ? -1 : 0, frontPart = inputValue.substr(0, caretPos.begin), backPart = inputValue.substr(caretPos.begin), frontBufferPart = buffer.substr(0, caretPos.begin + offset), backBufferPart = buffer.substr(caretPos.begin + offset);
30773                            var selection = caretPos, entries = "", isEntry = false;
30774                            if (frontPart !== frontBufferPart) {
30775                                var fpl = (isEntry = frontPart.length >= frontBufferPart.length) ? frontPart.length : frontBufferPart.length, i;
30776                                for (i = 0; frontPart.charAt(i) === frontBufferPart.charAt(i) && i < fpl; i++) {}
30777                                if (isEntry) {
30778                                    selection.begin = i - offset;
30779                                    entries += frontPart.slice(i, selection.end);
30780                                }
30781                            }
30782                            if (backPart !== backBufferPart) {
30783                                if (backPart.length > backBufferPart.length) {
30784                                    entries += backPart.slice(0, 1);
30785                                } else {
30786                                    if (backPart.length < backBufferPart.length) {
30787                                        selection.end += backBufferPart.length - backPart.length;
30788                                        if (!isEntry && opts.radixPoint !== "" && backPart === "" && frontPart.charAt(selection.begin + offset - 1) === opts.radixPoint) {
30789                                            selection.begin--;
30790                                            entries = opts.radixPoint;
30791                                        }
30792                                    }
30793                                }
30794                            }
30795                            writeBuffer(input, getBuffer(), {
30796                                begin: selection.begin + offset,
30797                                end: selection.end + offset
30798                            });
30799                            if (entries.length > 0) {
30800                                $.each(entries.split(""), function(ndx, entry) {
30801                                    var keypress = new $.Event("keypress");
30802                                    keypress.which = entry.charCodeAt(0);
30803                                    ignorable = false;
30804                                    EventHandlers.keypressEvent.call(input, keypress);
30805                                });
30806                            } else {
30807                                if (selection.begin === selection.end - 1) {
30808                                    selection.begin = seekPrevious(selection.begin + 1);
30809                                    if (selection.begin === selection.end - 1) {
30810                                        caret(input, selection.begin);
30811                                    } else {
30812                                        caret(input, selection.begin, selection.end);
30813                                    }
30814                                }
30815                                var keydown = new $.Event("keydown");
30816                                keydown.keyCode = opts.numericInput ? Inputmask.keyCode.BACKSPACE : Inputmask.keyCode.DELETE;
30817                                EventHandlers.keydownEvent.call(input, keydown);
30818                            }
30819                            e.preventDefault();
30820                        }
30821                    }
30822                },
30823                beforeInputEvent: function beforeInputEvent(e) {
30824                    if (e.cancelable) {
30825                        var input = this;
30826                        switch (e.inputType) {
30827                          case "insertText":
30828                            $.each(e.data.split(""), function(ndx, entry) {
30829                                var keypress = new $.Event("keypress");
30830                                keypress.which = entry.charCodeAt(0);
30831                                ignorable = false;
30832                                EventHandlers.keypressEvent.call(input, keypress);
30833                            });
30834                            return e.preventDefault();
30835
30836                          case "deleteContentBackward":
30837                            var keydown = new $.Event("keydown");
30838                            keydown.keyCode = Inputmask.keyCode.BACKSPACE;
30839                            EventHandlers.keydownEvent.call(input, keydown);
30840                            return e.preventDefault();
30841
30842                          case "deleteContentForward":
30843                            var keydown = new $.Event("keydown");
30844                            keydown.keyCode = Inputmask.keyCode.DELETE;
30845                            EventHandlers.keydownEvent.call(input, keydown);
30846                            return e.preventDefault();
30847                        }
30848                    }
30849                },
30850                setValueEvent: function setValueEvent(e) {
30851                    this.inputmask.refreshValue = false;
30852                    var input = this, value = e && e.detail ? e.detail[0] : arguments[1], value = value || input.inputmask._valueGet(true);
30853                    if ($.isFunction(opts.onBeforeMask)) value = opts.onBeforeMask.call(inputmask, value, opts) || value;
30854                    value = value.toString().split("");
30855                    checkVal(input, true, false, value);
30856                    undoValue = getBuffer().join("");
30857                    if ((opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("")) {
30858                        input.inputmask._valueSet("");
30859                    }
30860                },
30861                focusEvent: function focusEvent(e) {
30862                    var input = this, nptValue = input.inputmask._valueGet();
30863                    if (opts.showMaskOnFocus) {
30864                        if (nptValue !== getBuffer().join("")) {
30865                            writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()));
30866                        } else if (mouseEnter === false) {
30867                            caret(input, seekNext(getLastValidPosition()));
30868                        }
30869                    }
30870                    if (opts.positionCaretOnTab === true && mouseEnter === false) {
30871                        EventHandlers.clickEvent.apply(input, [ e, true ]);
30872                    }
30873                    undoValue = getBuffer().join("");
30874                },
30875                mouseleaveEvent: function mouseleaveEvent(e) {
30876                    var input = this;
30877                    mouseEnter = false;
30878                    if (opts.clearMaskOnLostFocus && document.activeElement !== input) {
30879                        HandleNativePlaceholder(input, originalPlaceholder);
30880                    }
30881                },
30882                clickEvent: function clickEvent(e, tabbed) {
30883                    function doRadixFocus(clickPos) {
30884                        if (opts.radixPoint !== "") {
30885                            var vps = getMaskSet().validPositions;
30886                            if (vps[clickPos] === undefined || vps[clickPos].input === getPlaceholder(clickPos)) {
30887                                if (clickPos < seekNext(-1)) return true;
30888                                var radixPos = $.inArray(opts.radixPoint, getBuffer());
30889                                if (radixPos !== -1) {
30890                                    for (var vp in vps) {
30891                                        if (radixPos < vp && vps[vp].input !== getPlaceholder(vp)) {
30892                                            return false;
30893                                        }
30894                                    }
30895                                    return true;
30896                                }
30897                            }
30898                        }
30899                        return false;
30900                    }
30901                    var input = this;
30902                    setTimeout(function() {
30903                        if (document.activeElement === input) {
30904                            var selectedCaret = caret(input);
30905                            if (tabbed) {
30906                                if (isRTL) {
30907                                    selectedCaret.end = selectedCaret.begin;
30908                                } else {
30909                                    selectedCaret.begin = selectedCaret.end;
30910                                }
30911                            }
30912                            if (selectedCaret.begin === selectedCaret.end) {
30913                                switch (opts.positionCaretOnClick) {
30914                                  case "none":
30915                                    break;
30916
30917                                  case "select":
30918                                    caret(input, 0, getBuffer().length);
30919                                    break;
30920
30921                                  case "ignore":
30922                                    caret(input, seekNext(getLastValidPosition()));
30923                                    break;
30924
30925                                  case "radixFocus":
30926                                    if (doRadixFocus(selectedCaret.begin)) {
30927                                        var radixPos = getBuffer().join("").indexOf(opts.radixPoint);
30928                                        caret(input, opts.numericInput ? seekNext(radixPos) : radixPos);
30929                                        break;
30930                                    }
30931
30932                                  default:
30933                                    var clickPosition = selectedCaret.begin, lvclickPosition = getLastValidPosition(clickPosition, true), lastPosition = seekNext(lvclickPosition);
30934                                    if (clickPosition < lastPosition) {
30935                                        caret(input, !isMask(clickPosition, true) && !isMask(clickPosition - 1, true) ? seekNext(clickPosition) : clickPosition);
30936                                    } else {
30937                                        var lvp = getMaskSet().validPositions[lvclickPosition], tt = getTestTemplate(lastPosition, lvp ? lvp.match.locator : undefined, lvp), placeholder = getPlaceholder(lastPosition, tt.match);
30938                                        if (placeholder !== "" && getBuffer()[lastPosition] !== placeholder && tt.match.optionalQuantifier !== true && tt.match.newBlockMarker !== true || !isMask(lastPosition, opts.keepStatic) && tt.match.def === placeholder) {
30939                                            var newPos = seekNext(lastPosition);
30940                                            if (clickPosition >= newPos || clickPosition === lastPosition) {
30941                                                lastPosition = newPos;
30942                                            }
30943                                        }
30944                                        caret(input, lastPosition);
30945                                    }
30946                                    break;
30947                                }
30948                            }
30949                        }
30950                    }, 0);
30951                },
30952                cutEvent: function cutEvent(e) {
30953                    var input = this, $input = $(input), pos = caret(input), ev = e.originalEvent || e;
30954                    var clipboardData = window.clipboardData || ev.clipboardData, clipData = isRTL ? getBuffer().slice(pos.end, pos.begin) : getBuffer().slice(pos.begin, pos.end);
30955                    clipboardData.setData("text", isRTL ? clipData.reverse().join("") : clip
30955Data.join(""));
30956                    if (document.execCommand) document.execCommand("copy");
30957                    handleRemove(input, Inputmask.keyCode.DELETE, pos);
30958                    writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue !== getBuffer().join(""));
30959                },
30960                blurEvent: function blurEvent(e) {
30961                    var $input = $(this), input = this;
30962                    if (input.inputmask) {
30963                        HandleNativePlaceholder(input, originalPlaceholder);
30964                        var nptValue = input.inputmask._valueGet(), buffer = getBuffer().slice();
30965                        if (nptValue !== "" || colorMask !== undefined) {
30966                            if (opts.clearMaskOnLostFocus) {
30967                                if (getLastValidPosition() === -1 && nptValue === getBufferTemplate().join("")) {
30968                                    buffer = [];
30969                                } else {
30970                                    clearOptionalTail(buffer);
30971                                }
30972                            }
30973                            if (isComplete(buffer) === false) {
30974                                setTimeout(function() {
30975                                    $input.trigger("incomplete");
30976                                }, 0);
30977                                if (opts.clearIncomplete) {
30978                                    resetMaskSet();
30979                                    if (opts.clearMaskOnLostFocus) {
30980                                        buffer = [];
30981                                    } else {
30982                                        buffer = getBufferTemplate().slice();
30983                                    }
30984                                }
30985                            }
30986                            writeBuffer(input, buffer, undefined, e);
30987                        }
30988                        if (undoValue !== getBuffer().join("")) {
30989                            undoValue = buffer.join("");
30990                            $input.trigger("change");
30991                        }
30992                    }
30993                },
30994                mouseenterEvent: function mouseenterEvent(e) {
30995                    var input = this;
30996                    mouseEnter = true;
30997                    if (document.activeElement !== input && opts.showMaskOnHover) {
30998                        HandleNativePlaceholder(input, (isRTL ? getBuffer().slice().reverse() : getBuffer()).join(""));
30999                    }
31000                },
31001                submitEvent: function submitEvent(e) {
31002                    if (undoValue !== getBuffer().join("")) {
31003                        $el.trigger("change");
31004                    }
31005                    if (opts.clearMaskOnLostFocus && getLastValidPosition() === -1 && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("")) {
31006                        el.inputmask._valueSet("");
31007                    }
31008                    if (opts.clearIncomplete && isComplete(getBuffer()) === false) {
31009                        el.inputmask._valueSet("");
31010                    }
31011                    if (opts.removeMaskOnSubmit) {
31012                        el.inputmask._valueSet(el.inputmask.unmaskedvalue(), true);
31013                        setTimeout(function() {
31014                            writeBuffer(el, getBuffer());
31015                        }, 0);
31016                    }
31017                },
31018                resetEvent: function resetEvent(e) {
31019                    el.inputmask.refreshValue = true;
31020                    setTimeout(function() {
31021                        $el.trigger("setvalue");
31022                    }, 0);
31023                }
31024            };
31025            function checkVal(input, writeOut, strict, nptvl, initiatingEvent) {
31026                var inputmask = this || input.inputmask, inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = undefined;
31027                function isTemplateMatch(ndx, charCodes) {
31028                    var charCodeNdx = getMaskTemplate(true, 0, false).slice(ndx, seekNext(ndx)).join("").replace(/'/g, "").indexOf(charCodes);
31029                    return charCodeNdx !== -1 && !isMask(ndx) && (getTest(ndx).match.nativeDef === charCodes.charAt(0) || getTest(ndx).match.fn === null && getTest(ndx).match.nativeDef === "'" + charCodes.charAt(0) || getTest(ndx).match.nativeDef === " " && (getTest(ndx + 1).match.nativeDef === charCodes.charAt(0) || getTest(ndx + 1).match.fn === null && getTest(ndx + 1).match.nativeDef === "'" + charCodes.charAt(0)));
31030                }
31031                resetMaskSet();
31032                if (!strict && opts.autoUnmask !== true) {
31033                    var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""), matches = inputValue.join("").match(new RegExp("^" + Inputmask.escapeRegex(staticInput), "g"));
31034                    if (matches && matches.length > 0) {
31035                        inputValue.splice(0, matches.length * staticInput.length);
31036                        initialNdx = seekNext(initialNdx);
31037                    }
31038                } else {
31039                    initialNdx = seekNext(initialNdx);
31040                }
31041                if (initialNdx === -1) {
31042                    getMaskSet().p = seekNext(initialNdx);
31043                    initialNdx = 0;
31044                } else getMaskSet().p = initialNdx;
31045                inputmask.caretPos = {
31046                    begin: initialNdx
31047                };
31048                $.each(inputValue, function(ndx, charCode) {
31049                    if (charCode !== undefined) {
31050                        if (getMaskSet().validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, true) && isValid(ndx, inputValue[ndx], true, undefined, undefined, true) === false) {
31051                            getMaskSet().p++;
31052                        } else {
31053                            var keypress = new $.Event("_checkval");
31054                            keypress.which = charCode.charCodeAt(0);
31055                            charCodes += charCode;
31056                            var lvp = getLastValidPosition(undefined, true);
31057                            if (!isTemplateMatch(initialNdx, charCodes)) {
31058                                result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, inputmask.caretPos.begin);
31059                                if (result) {
31060                                    initialNdx = inputmask.caretPos.begin + 1;
31061                                    charCodes = "";
31062                                }
31063                            } else {
31064                                result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, lvp + 1);
31065                            }
31066                            if (result) {
31067                                writeBuffer(undefined, getBuffer(), result.forwardPosition, keypress, false);
31068                                inputmask.caretPos = {
31069                                    begin: result.forwardPosition,
31070                                    end: result.forwardPosition
31071                                };
31072                            }
31073                        }
31074                    }
31075                });
31076                if (writeOut) writeBuffer(input, getBuffer(), result ? result.forwardPosition : undefined, initiatingEvent || new $.Event("checkval"), initiatingEvent && initiatingEvent.type === "input");
31077            }
31078            function unmaskedvalue(input) {
31079                if (input) {
31080                    if (input.inputmask === undefined) {
31081                        return input.value;
31082                    }
31083                    if (input.inputmask && input.inputmask.refreshValue) {
31084                        EventHandlers.setValueEvent.call(input);
31085                    }
31086                }
31087                var umValue = [], vps = getMaskSet().validPositions;
31088                for (var pndx in vps) {
31089                    if (vps[pndx].match && vps[pndx].match.fn != null) {
31090                        umValue.push(vps[pndx].input);
31091                    }
31092                }
31093                var unmaskedValue = umValue.length === 0 ? "" : (isRTL ? umValue.reverse() : umValue).join("");
31094                if ($.isFunction(opts.onUnMask)) {
31095                    var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("");
31096                    unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts);
31097                }
31098                return unmaskedValue;
31099            }
31100            function caret(input, begin, end, notranslate) {
31101                function translatePosition(pos) {
31102                    if (isRTL && typeof pos === "number" && (!opts.greedy || opts.placeholder !== "") && el) {
31103                        pos = el.inputmask._valueGet().length - pos;
31104                    }
31105                    return pos;
31106                }
31107                var range;
31108                if (begin !== undefined) {
31109                    if ($.isArray(begin)) {
31110                        end = isRTL ? begin[0] : begin[1];
31111                        begin = isRTL ? begin[1] : begin[0];
31112                    }
31113                    if (begin.begin !== undefined) {
31114                        end = isRTL ? begin.begin : begin.end;
31115                        begin = isRTL ? begin.end : begin.begin;
31116                    }
31117                    if (typeof begin === "number") {
31118                        begin = notranslate ? begin : translatePosition(begin);
31119                        end = notranslate ? end : translatePosition(end);
31120                        end = typeof end == "number" ? end : begin;
31121                        var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end;
31122                        input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0;
31123                        input.inputmask.caretPos = {
31124                            begin: begin,
31125                            end: end
31126                        };
31127                        if (input === document.activeElement) {
31128                            if ("selectionStart" in input) {
31129                                input.selectionStart = begin;
31130                                input.selectionEnd = end;
31131                            } else if (window.getSelection) {
31132                                range = document.createRange();
31133                                if (input.firstChild === undefined || input.firstChild === null) {
31134                                    var textNode = document.createTextNode("");
31135                                    input.appendChild(textNode);
31136                                }
31137                                range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length);
31138                                range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length);
31139                                range.collapse(true);
31140                                var sel = window.getSelection();
31141                                sel.removeAllRanges();
31142                                sel.addRange(range);
31143                            } else if (input.createTextRange) {
31144                                range = input.createTextRange();
31145                                range.collapse(true);
31146                                range.moveEnd("character", end);
31147                                range.moveStart("character", begin);
31148                                range.select();
31149                            }
31150                            renderColorMask(input, {
31151                                begin: begin,
31152                                end: end
31153                            });
31154                        }
31155                    }
31156                } else {
31157                    if ("selectionStart" in input) {
31158                        begin = input.selectionStart;
31159                        end = input.selectionEnd;
31160                    } else if (window.getSelection) {
31161                        range = window.getSelection().getRangeAt(0);
31162                        if (range.commonAncestorContainer.parentNode === input || range.commonAncestorContainer === input) {
31163                            begin = range.startOffset;
31164                            end = range.endOffset;
31165                        }
31166                    } else if (document.selection && document.selection.createRange) {
31167                        range = document.selection.createRange();
31168                        begin = 0 - range.duplicate().moveStart("character", -input.inputmask._valueGet().length);
31169                        end = begin + range.text.length;
31170                    }
31171                    return {
31172                        begin: notranslate ? begin : translatePosition(begin),
31173                        end: notranslate ? end : translatePosition(en
31173d)
31174                    };
31175                }
31176            }
31177            function determineLastRequiredPosition(returnDefinition) {
31178                var buffer = getMaskTemplate(true, getLastValidPosition(), true, true), bl = buffer.length, pos, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet().validPositions[lvp], ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined, testPos;
31179                for (pos = lvp + 1; pos < buffer.length; pos++) {
31180                    testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
31181                    ndxIntlzr = testPos.locator.slice();
31182                    positions[pos] = $.extend(true, {}, testPos);
31183                }
31184                var lvTestAlt = lvTest && lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation] : undefined;
31185                for (pos = bl - 1; pos > lvp; pos--) {
31186                    testPos = positions[pos];
31187                    if ((testPos.match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && testPos.match.fn != null || testPos.match.fn === null && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && getTests(pos)[0].def !== "")) && buffer[pos] === getPlaceholder(pos, testPos.match)) {
31188                        bl--;
31189                    } else break;
31190                }
31191                return returnDefinition ? {
31192                    l: bl,
31193                    def: positions[bl] ? positions[bl].match : undefined
31194                } : bl;
31195            }
31196            function clearOptionalTail(buffer) {
31197                buffer.length = 0;
31198                var template = getMaskTemplate(true, 0, true, undefined, true), lmnt, validPos;
31199                while (lmnt = template.shift(), lmnt !== undefined) {
31200                    buffer.push(lmnt);
31201                }
31202                return buffer;
31203            }
31204            function isComplete(buffer) {
31205                if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts);
31206                if (opts.repeat === "*") return undefined;
31207                var complete = false, lrp = determineLastRequiredPosition(true), aml = seekPrevious(lrp.l);
31208                if (lrp.def === undefined || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
31209                    complete = true;
31210                    for (var i = 0; i <= aml; i++) {
31211                        var test = getTestTemplate(i).match;
31212                        if (test.fn !== null && getMaskSet().validPositions[i] === undefined && test.optionality !== true && test.optionalQuantifier !== true || test.fn === null && buffer[i] !== getPlaceholder(i, test)) {
31213                            complete = false;
31214                            break;
31215                        }
31216                    }
31217                }
31218                return complete;
31219            }
31220            function handleRemove(input, k, pos, strict, fromIsValid) {
31221                if (opts.numericInput || isRTL) {
31222                    if (k === Inputmask.keyCode.BACKSPACE) {
31223                        k = Inputmask.keyCode.DELETE;
31224                    } else if (k === Inputmask.keyCode.DELETE) {
31225                        k = Inputmask.keyCode.BACKSPACE;
31226                    }
31227                    if (isRTL) {
31228                        var pend = pos.end;
31229                        pos.end = pos.begin;
31230                        pos.begin = pend;
31231                    }
31232                }
31233                if (k === Inputmask.keyCode.BACKSPACE && pos.end - pos.begin < 1) {
31234                    pos.begin = seekPrevious(pos.begin);
31235                    if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) {
31236                        pos.begin--;
31237                    }
31238                } else if (k === Inputmask.keyCode.DELETE && pos.begin === pos.end) {
31239                    pos.end = isMask(pos.end, true) && getMaskSet().validPositions[pos.end] && getMaskSet().validPositions[pos.end].input !== opts.radixPoint ? pos.end + 1 : seekNext(pos.end) + 1;
31240                    if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) {
31241                        pos.end++;
31242                    }
31243                }
31244                revalidateMask(pos);
31245                if (strict !== true && opts.keepStatic !== false || opts.regex !== null) {
31246                    var result = alternate(true);
31247                    if (result) {
31248                        var newPos = result.caret !== undefined ? result.caret : result.pos ? seekNext(result.pos.begin ? result.pos.begin : result.pos) : getLastValidPosition(-1, true);
31249                        if (k !== Inputmask.keyCode.DELETE || pos.begin > newPos) {
31250                            pos.begin == newPos;
31251                        }
31252                    }
31253                }
31254                var lvp = getLastValidPosition(pos.begin, true);
31255                if (lvp < pos.begin || pos.begin === -1) {
31256                    getMaskSet().p = seekNext(lvp);
31257                } else if (strict !== true) {
31258                    getMaskSet().p = pos.begin;
31259                    if (fromIsValid !== true) {
31260                        while (getMaskSet().p < lvp && getMaskSet().validPositions[getMaskSet().p] === undefined) {
31261                            getMaskSet().p++;
31262                        }
31263                    }
31264                }
31265            }
31266            function initializeColorMask(input) {
31267                var computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null);
31268                function findCaretPos(clientx) {
31269                    var e = document.createElement("span"), caretPos;
31270                    for (var style in computedStyle) {
31271                        if (isNaN(style) && style.indexOf("font") !== -1) {
31272                            e.style[style] = computedStyle[style];
31273                        }
31274                    }
31275                    e.style.textTransform = computedStyle.textTransform;
31276                    e.style.letterSpacing = computedStyle.letterSpacing;
31277                    e.style.position = "absolute";
31278                    e.style.height = "auto";
31279                    e.style.width = "auto";
31280                    e.style.visibility = "hidden";
31281                    e.style.whiteSpace = "nowrap";
31282                    document.body.appendChild(e);
31283                    var inputText = input.inputmask._valueGet(), previousWidth = 0, itl;
31284                    for (caretPos = 0, itl = inputText.length; caretPos <= itl;
31284 caretPos++) {
31285                        e.innerHTML += inputText.charAt(caretPos) || "_";
31286                        if (e.offsetWidth >= clientx) {
31287                            var offset1 = clientx - previousWidth;
31288                            var offset2 = e.offsetWidth - clientx;
31289                            e.innerHTML = inputText.charAt(caretPos);
31290                            offset1 -= e.offsetWidth / 3;
31291                            caretPos = offset1 < offset2 ? caretPos - 1 : caretPos;
31292                            break;
31293                        }
31294                        previousWidth = e.offsetWidth;
31295                    }
31296                    document.body.removeChild(e);
31297                    return caretPos;
31298                }
31299                var template = document.createElement("div");
31300                template.style.width = computedStyle.width;
31301                template.style.textAlign = computedStyle.textAlign;
31302                colorMask = document.createElement("div");
31303                input.inputmask.colorMask = colorMask;
31304                colorMask.className = "im-colormask";
31305                input.parentNode.insertBefore(colorMask, input);
31306                input.parentNode.removeChild(input);
31307                colorMask.appendChild(input);
31308                colorMask.appendChild(template);
31309                input.style.left = template.offsetLeft + "px";
31310                $(colorMask).on("mouseleave", function(e) {
31311                    return EventHandlers.mouseleaveEvent.call(input, [ e ]);
31312                });
31313                $(colorMask).on("mouseenter", function(e) {
31314                    return EventHandlers.mouseenterEvent.call(input, [ e ]);
31315                });
31316                $(colorMask).on("click", function(e) {
31317                    caret(input, findCaretPos(e.clientX));
31318                    return EventHandlers.clickEvent.call(input, [ e ]);
31319                });
31320            }
31321            function renderColorMask(input, caretPos, clear) {
31322                var maskTemplate = [], isStatic = false, test, testPos, ndxIntlzr, pos = 0;
31323                function setEntry(entry) {
31324                    if (entry === undefined) entry = "";
31325                    if (!isStatic && (test.fn === null || testPos.input === undefined)) {
31326                        isStatic = true;
31327                        maskTemplate.push("<span class='im-static'>" + entry);
31328                    } else if (isStatic && (test.fn !== null && testPos.input !== undefined || test.def === "")) {
31329                        isStatic = false;
31330                        var mtl = maskTemplate.length;
31331                        maskTemplate[mtl - 1] = maskTemplate[mtl - 1] + "</span>";
31332                        maskTemplate.push(entry);
31333                    } else maskTemplate.push(entry);
31334                }
31335                function setCaret() {
31336                    if (document.activeElement === input) {
31337                        maskTemplate.splice(caretPos.begin, 0, caretPos.begin === caretPos.end || caretPos.end > getMaskSet().maskLength ? '<mark class="im-caret" style="border-right-width: 1px;border-right-style: solid;">' : '<mark class="im-caret-select">');
31338                        maskTemplate.splice(caretPos.end + 1, 0, "</mark>");
31339                    }
31340                }
31341                if (colorMask !== undefined) {
31342                    var buffer = getBuffer();
31343                    if (caretPos === undefined) {
31344                        caretPos = caret(input);
31345                    } else if (caretPos.begin === undefined) {
31346                        caretPos = {
31347                            begin: caretPos,
31348                            end: caretPos
31349                        };
31350                    }
31351                    if (clear !== true) {
31352                        var lvp = getLastValidPosition();
31353                        do {
31354                            if (getMaskSet().validPositions[pos]) {
31355                                testPos = getMaskSet().validPositions[pos];
31356                                test = testPos.match;
31357                                ndxIntlzr = testPos.locator.slice();
31358                                setEntry(buffer[pos]);
31359                            } else {
31360                                testPos = getTestTemplate(pos, ndxIntlzr, pos - 1);
31361                                test = testPos.match;
31362                                ndxIntlzr = testPos.locator.slice();
31363                                if (opts.jitMasking === false || pos < lvp || typeof opts.jitMasking === "number" && isFinite(opts.jitMasking) && opts.jitMasking > pos) {
31364                                    setEntry(getPlaceholder(pos, test));
31365                                } else isStatic = false;
31366                            }
31367                            pos++;
31368                        } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || lvp > pos || isStatic);
31369                        if (isStatic) setEntry();
31370                        setCaret();
31371                    }
31372                    var template = colorMask.getElementsByTagName("div")[0];
31373                    template.innerHTML = maskTemplate.join("");
31374                    input.inputmask.positionColorMask(input, template);
31375                }
31376            }
31377            function mask(elem) {
31378                function isElementTypeSupported(input, opts) {
31379                    function patchValueProperty(npt) {
31380                        var valueGet;
31381                        var valueSet;
31382                        function patchValhook(type) {
31383                            if ($.valHooks && ($.valHooks[type] === undefined || $.valHooks[type].inputmaskpatch !== true)) {
31384                                var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
31385                                    return elem.value;
31386                                };
31387                                var valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
31388                                    elem.value = value;
31389                                    return elem;
31390                                };
31391                                $.valHooks[type] = {
31392                                    get: function get(elem) {
31393                                        if (elem.inputmask) {
31394                                            if (elem.inputmask.opts.autoUnmask) {
31395                                                return elem.inputmask.unmaskedvalue();
31396                                            } else {
31397                                                var result = valhookGet(elem);
31398                                                return getLastValidPosition(undefined, undefined, elem.inputmask.maskset.validPositions) !== -1 || opts.nullable !== true ? result : "";
31399                                            }
31400                                        } else return valhookGet(elem);
31401                                    },
31402                                    set: function set(elem, value) {
31403                                        var $elem = $(elem), result;
31404                                        result = valhookSet(elem, value);
31405                                        if (elem.inputmask) {
31406                                            $elem.trigger("setvalue", [ value ]);
31407                                        }
31408                                        return result;
31409                                    },
31410                                    inputmaskpatch: true
31411                                };
31412                            }
31413                        }
31414                        function getter() {
31415                            if (this.inputmask) {
31416                                return this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : getLastValidPosition() !== -1 || opts.nullable !== true ? document.activeElement === this && opts.clearMaskOnLostFocus ? (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") : valueGet.call(this) : "";
31417                            } else return valueGet.call(this);
31418                        }
31419                        function setter(value) {
31420                            valueSet.call(this, value);
31421                            if (this.inputmask) {
31422                                $(this).trigger("setvalue", [ value ]);
31423                            }
31424                        }
31425                        function installNativeValueSetFallback(npt) {
31426                            EventRuler.on(npt, "mouseenter", function(event) {
31427                                var $input = $(this), input = this, value = input.inputmask._valueGet();
31428                                if (value !== getBuffer().join("")) {
31429                                    $input.trigger("setvalue");
31430                                }
31431                            });
31432                        }
31433                        if (!npt.inputmask.__valueGet) {
31434                            if (opts.noValuePatching !== true) {
31435                                if (Object.getOwnPropertyDescriptor) {
31436                                    if (typeof Object.getPrototypeOf 
31436!== "function") {
31437                                        Object.getPrototypeOf = _typeof("test".__proto__) === "object" ? function(object) {
31438                                            return object.__proto__;
31439                                        } : function(object) {
31440                                            return object.constructor.prototype;
31441                                        };
31442                                    }
31443                                    var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : undefined;
31444                                    if (valueProperty && valueProperty.get && valueProperty.set) {
31445                                        valueGet = valueProperty.get;
31446                                        valueSet = valueProperty.set;
31447                                        Object.defineProperty(npt, "value", {
31448                                            get: getter,
31449                                            set: setter,
31450                                            configurable: true
31451                                        });
31452                                    } else if (npt.tagName !== "INPUT") {
31453                                        valueGet = function valueGet() {
31454                                            return this.textContent;
31455                                        };
31456                                        valueSet = function valueSet(value) {
31457                                            this.textContent = value;
31458                                        };
31459                                        Object.defineProperty(npt, "value", {
31460                                            get: getter,
31461                                            set: setter,
31462                                            configurable: true
31463                                        });
31464                                    }
31465                                } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) {
31466                                    valueGet = npt.__lookupGetter__("value");
31467                                    valueSet = npt.__lookupSetter__("value");
31468                                    npt.__defineGetter__("value", getter);
31469                                    npt.__defineSetter__("value", setter);
31470                                }
31471                                npt.inputmask.__valueGet = valueGet;
31472                                npt.inputmask.__valueSet = valueSet;
31473                            }
31474                            npt.inputmask._valueGet = function(overruleRTL) {
31475                                return isRTL && overruleRTL !== true ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el);
31476                            };
31477                            npt.inputmask._valueSet = function(value, overruleRTL) {
31478                                valueSet.call(this.el, value === null || value === undefined ? "" : overruleRTL !== true && isRTL ? value.split("").reverse().join("") : value);
31479                            };
31480                            if (valueGet === undefined) {
31481                                valueGet = function valueGet() {
31482                                    return this.value;
31483                                };
31484                                valueSet = function valueSet(value) {
31485                                    this.value = value;
31486                                };
31487                                patchValhook(npt.type);
31488                                installNativeValueSetFallback(npt);
31489                            }
31490                        }
31491                    }
31492                    var elementType = input.getAttribute("type");
31493                    var isSupported = input.tagName === "INPUT" && $.inArray(elementType, opts.supportsInputType) !== -1 || input.isContentEditable || input.tagName === "TEXTAREA";
31494                    if (!isSupported) {
31495                        if (input.tagName === "INPUT") {
31496                            var el = document.createElement("input");
31497                            el.setAttribute("type", elementType);
31498                            isSupported = el.type === "text";
31499                            el = null;
31500                        } else isSupported = "partial";
31501                    }
31502                    if (isSupported !== false) {
31503                        patchValueProperty(input);
31504                    } else input.inputmask = undefined;
31505                    return isSupported;
31506                }
31507                EventRuler.off(elem);
31508                var isSupported = isElementTypeSupported(elem, opts);
31509                if (isSupported !== false) {
31510                    el = elem;
31511                    $el = $(el);
31512                    originalPlaceholder = el.placeholder;
31513                    maxLength = el !== undefined ? el.maxLength : undefined;
31514                    if (maxLength === -1) maxLength = undefined;
31515                    if (opts.colorMask === true) {
31516                        initializeColorMask(el);
31517                    }
31518                    if (mobile) {
31519                        if ("inputmode" in el) {
31520                            el.inputmode = opts.inputmode;
31521                            el.setAttribute("inputmode", opts.inputmode);
31522                        }
31523                        if (opts.disablePredictiveText === true) {
31524                            if ("autocorrect" in el) {
31525                                el.autocorrect = false;
31526                            } else {
31527                                if (opts.colorMask !== true) {
31528                                    initializeColorMask(el);
31529                                }
31530                                el.type = "password";
31531                            }
31532                        }
31533                    }
31534                    if (isSupported === true) {
31535                        el.setAttribute("im-insert", opts.insertMode);
31536                        EventRuler.on(el, "submit", EventHandlers.submitEvent);
31537                        EventRuler.on(el, "reset", EventHandlers.resetEvent);
31538                        EventRuler.on(el, "blur", EventHandlers.blurEvent);
31539                        EventRuler.on(el, "focus", EventHandlers.focusEvent);
31540                        if (opts.colorMask !== true) {
31541                            EventRuler.on(el, "click", EventHandlers.clickEvent);
31542                            EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent);
31543                            EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent);
31544                        }
31545                        EventRuler.on(el, "paste", EventHandlers.pasteEvent);
31546                        EventRuler.on(el, "cut", EventHandlers.cutEvent);
31547                        EventRuler.on(el, "complete", opts.oncomplete);
31548                        EventRuler.on(el, "incomplete", opts.onincomplete);
31549                        EventRuler.on(el, "cleared", opts.oncleared);
31550                        if (!mobile && opts.inputEventOnly !== true) {
31551                            EventRuler.on(el, "keydown", EventHandlers.keydownEvent);
31552                            EventRuler.on(el, "keypress", EventHandlers.keypressEvent);
31553                        } else {
31554                            el.removeAttribute("maxLength");
31555                        }
31556                        EventRuler.on(el, "input", EventHandlers.inputFallBackEvent);
31557                        EventRuler.on(el, "beforeinput", EventHandlers.beforeInputEvent);
31558                    }
31559                    EventRuler.on(el, "setvalue", EventHandlers.setValueEvent);
31560                    undoValue = getBufferTemplate().join("");
31561                    if (el.inputmask._valueGet(true) !== "" || opts.clearMaskOnLostFocus === false || document.activeElement === el) {
31562                        var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, el.inputmask._valueGet(true), opts) || el.inputmask._valueGet(true) : el.inputmask._valueGet(true);
31563                        if (initialValue !== "") checkVal(el, true, false, initialValue.split(""));
31564                        var buffer = getBuffer().slice();
31565                        undoValue = buffer.join("");
31566                        if (isComplete(buffer) === false) {
31567                            if (opts.clearIncomplete) {
31568                                resetMaskSet();
31569                            }
31570                        }
31571                        if (opts.clearMaskOnLostFocus && document.activeElement !== el) {
31572                            if (getLastValidPosition() === -1) {
31573                                buffer = [];
31574                            } else {
31575                                clearOptionalTail(buffer);
31576                            }
31577                        }
31578                        if (opts.clearMaskOnLostFocus === false || opts.showMaskOnFocus && document.activeElement === el || el.inputmask._valueGet(true) !== "") writeBuffer(el, buffer);
31579                        if (document.activeElement === el) {
31580                            caret(el, seekNext(getLastValidPosition()));
31581                        }
31582                    }
31583                }
31584            }
31585            var valueBuffer;
31586            if (actionObj !== undefined) {
31587                switch (actionObj.action) {
31588                  case "isComplete":
31589                    el = actionObj.el;
31590                    return isComplete(getBuffer());
31591
31592                  case "unmaskedvalue":
31593                    if (el === undefined || actionObj.value !== undefined) {
31594                        valueBuffer = actionObj.value;
31595                        valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer : valueBuffer).split("");
31596                        checkVal.call(this, undefined, false, false, valueBuffer);
31597                        if ($.isFunction(opts.onBeforeWrite)) opts.onBeforeWrite.call(inputmask, undefined, getBuffer(), 0, opts);
31598                    }
31599                    return unmaskedvalue(el);
31600
31601                  case "mask":
31602                    mask(el);
31603                    break;
31604
31605                  case "format":
31606                    valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value : actionObj.value).split("");
31607                    checkVal.call(this, undefined, true, false, valueBuffer);
31608                    if (actionObj.metadata) {
31609                        return {
31610                            value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
31611                            metadata: maskScope.call(this, {
31612                                action: "getmetadata"
31613                            }, maskset, opts)
31614                        };
31615                    }
31616                    return isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");
31617
31618                  case "isValid":
31619                    if (actionObj.value) {
31620                        valueBuffer = actionObj.value.split("");
31621                        checkVal.call(this, undefined, true, true, valueBuffer);
31622                    } else {
31623                        actionObj.value = getBuffer().join("");
31624                    }
31625                    var buffer = getBuffer();
31626                    var rl = determineLastRequiredPosition(), lmib = buffer.length - 1;
31627                    for (;lmib > rl; lmib--) {
31628                        if (isMask(lmib)) break;
31629                    }
31630                    buffer.splice(rl, lmib + 1 - rl);
31631                    return isComplete(buffer) && actionObj.value === getBuffer().join("");
31632
31633                  case "getemptymask":
31634                    return getBufferTemplate().join("");
31635
31636                  case "remove":
31637                    if (el && el.inputmask) {
31638                        $.data(el, "_inputmask_opts", null);
31639                        $el = $(el);
31640                        el.inputmask._valueSet(opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(true));
31641                        EventRuler.off(el);
31642                        if (el.inputmask.colorMask) {
31643                            colorMask = el.inputmask.colorMask;
31644                            colorMask.removeChild(el);
31645                            colorMask.parentNode.insertBefore(el, colorMask);
31646                            colorMask.parentNode.removeChild(colorMask);
31647                        }
31648                        var valueProperty;
31649                        if (Object.getOwnPropertyDescriptor && Ob
31649ject.getPrototypeOf) {
31650                            valueProperty = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value");
31651                            if (valueProperty) {
31652                                if (el.inputmask.__valueGet) {
31653                                    Object.defineProperty(el, "value", {
31654                                        get: el.inputmask.__valueGet,
31655                                        set: el.inputmask.__valueSet,
31656                                        configurable: true
31657                                    });
31658                                }
31659                            }
31660                        } else if (document.__lookupGetter__ && el.__lookupGetter__("value")) {
31661                            if (el.inputmask.__valueGet) {
31662                                el.__defineGetter__("value", el.inputmask.__valueGet);
31663                                el.__defineSetter__("value", el.inputmask.__valueSet);
31664                            }
31665                        }
31666                        el.inputmask = undefined;
31667                    }
31668                    return el;
31669                    break;
31670
31671                  case "getmetadata":
31672                    if ($.isArray(maskset.metadata)) {
31673                        var maskTarget = getMaskTemplate(true, 0, false).join("");
31674                        $.each(maskset.metadata, function(ndx, mtdt) {
31675                            if (mtdt.mask === maskTarget) {
31676                                maskTarget = mtdt;
31677                                return false;
31678                            }
31679                        });
31680                        return maskTarget;
31681                    }
31682                    return maskset.metadata;
31683                }
31684            }
31685        }
31686        return Inputmask;
31687    });
31688}, function(module, exports, __webpack_require__) {
31689    "use strict";
31690    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
31691    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
31692        return typeof obj;
31693    } : function(obj) {
31694        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
31695    };
31696    (function(factory) {
31697        if (true) {
31698            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(4) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
31699            __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
31700            __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
31701        } else {}
31702    })(function($) {
31703        return $;
31704    });
31705}, function(module, exports) {
31706    module.exports = jQuery;
31707}, function(module, exports, __webpack_require__) {
31708    "use strict";
31709    var __WEBPACK_AMD_DEFINE_RESULT__;
31710    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
31711        return typeof obj;
31712    } : function(obj) {
31713        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
31714    };
31715    if (true) !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
31716        return typeof window !== "undefined" ? window : new (eval("require('jsdom').JSDOM"))("").window;
31717    }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); else {}
31718}, function(module, exports, __webpack_require__) {
31719    "use strict";
31720    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
31721    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
31722        return typeof obj;
31723    } : function(obj) {
31724        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
31725    };
31726    (function(factory) {
31727        if (true) {
31728            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
31729            __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
31730            __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
31731        } else {}
31732    })(function(Inputmask) {
31733        var $ = Inputmask.dependencyLib;
31734        var formatCode = {
31735            d: [ "[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", Date.prototype.getDate ],
31736            dd: [ "0[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", function() {
31737                return pad(Date.prototype.getDate.call(this), 2);
31738            } ],
31739            ddd: [ "" ],
31740            dddd: [ "" ],
31741            m: [ "[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
31742                return Date.prototype.getMonth.call(this) + 1;
31743            } ],
31744            mm: [ "0[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
31745                return pad(Date.prototype.getMonth.call(this) + 1, 2);
31746            } ],
31747            mmm: [ "" ],
31748            mmmm: [ "" ],
31749            yy: [ "[0-9]{2}", Date.prototype.setFullYear, "year", function() {
31750                return pad(Date.prototype.getFullYear.call(this), 2);
31751            } ],
31752            yyyy: [ "[0-9]{4}", Date.prototype.setFullYear, "year", function() {
31753                return pad(Date.prototype.getFullYear.call(this), 4);
31754            } ],
31755            h: [ "[1-9]|1[0-2]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
31756            hh: [ "0[1-9]|1[0-2]", Date.prototype.setHours, "hours", function() {
31757                return pad(Date.prototype.getHours.call(this), 2);
31758            } ],
31759            hhh: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ],
31760            H: [ "1?[0-9]|2[0-3]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
31761            HH: [ "0[0-9]|1[0-9]|2[0-3]", Date.prototype.setHours, "hours", function() {
31762                return pad(Date.prototype.getHours.call(this), 2);
31763            } ],
31764            HHH: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ],
31765            M: [ "[1-5]?[0-9]", Date.prototype.setMinutes, "minutes", Date.prototype.getMinutes ],
31766            MM: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setMinutes, "minutes", function() {
31767                return pad(Date.prototype.getMinutes.call(this), 2);
31768            } ],
31769            ss: [ "[0-5][0-9]", Date.prototype.setSeconds, "seconds", function() {
31770                return pad(Date.prototype.getSeconds.call(this), 2);
31771            } ],
31772            l: [ "[0-9]{3}", Date.prototype.setMilliseconds, "milliseconds", function() {
31773                return pad(Date.prototype.getMilliseconds.call(this), 3);
31774            } ],
31775            L: [ "[0-9]{2}", Date.prototype.setMilliseconds, "milliseconds", function() {
31776                return pad(Date.prototype.getMilliseconds.call(this), 2);
31777            } ],
31778            t: [ "[ap]" ],
31779            tt: [ "[ap]m" ],
31780            T: [ "[AP]" ],
31781            TT: [ "[AP]M" ],
31782            Z: [ "" ],
31783            o: [ "" ],
31784            S: [ "" ]
31785        }, formatAlias = {
31786            isoDate: "yyyy-mm-dd",
31787            isoTime: "HH:MM:ss",
31788            isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
31789            isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
31790        };
31791        function getTokenizer(opts) {
31792            if (!opts.tokenizer) {
31793                var tokens = [];
31794                for (var ndx in formatCode) {
31795                    if (tokens.indexOf(ndx[0]) === -1) tokens.push(ndx[0]);
31796                }
31797                opts.tokenizer = "(" + tokens.join("+|") + ")+?|.";
31798                opts.tokenizer = new RegExp(opts.tokenizer, "g");
31799            }
31800            return opts.tokenizer;
31801        }
31802        function isValidDate(dateParts, currentResult) {
31803            return !isFinite(dateParts.rawday) || dateParts.day == "29" && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day ? currentResult : false;
31804        }
31805        function isDateInRange(dateParts, opts) {
31806            var result = true;
31807            if (opts.min) {
31808                if (dateParts["rawyear"]) {
31809                    var rawYear = dateParts["rawyear"].replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length);
31810                    result = minYear <= rawYear;
31811                }
31812                if (dateParts["year"] === dateParts["rawyear"]) {
31813                    if (opts.min.date.getTime() === opts.min.date.getTime()) {
31814                        result = opts.min.date.getTime() <= dateParts.date.getTime();
31815                    }
31816                }
31817            }
31818            if (result && opts.max && opts.max.date.getTime() === opts.max.date.getTime()) {
31819                result = opts.max.date.getTime() >= dateParts.date.getTime();
31820            }
31821            return result;
31822        }
31823        function parse(format, dateObjValue, opts, raw) {
31824            var mask = "", match;
31825            while (match = getTokenizer(opts).exec(format)) {
31826                if (dateObjValue === undefined) {
31827                    if (formatCode[match[0]]) {
31828                        mask += "(" + formatCode[match[0]][0] + ")";
31829                    } else {
31830                        switch (match[0]) {
31831                          case "[":
31832                            mask += "(";
31833                            break;
31834
31835                          case "]":
31836                            mask += ")?";
31837                            break;
31838
31839                          default:
31840                            mask += Inputmask.escapeRegex(match[0]);
31841                        }
31842                    }
31843                } else {
31844                    if (formatCode[match[0]]) {
31845                        if (raw !== true && formatCode[match[0]][3]) {
31846                            var getFn = formatCode[match[0]][3];
31847                            mask += getFn.call(dateObjValue.date);
31848                        } else if (formatCode[match[0]][2]) mask += dateObjValue["raw" + formatCode[match[0]][2]]; else mask += match[0];
31849                    } else mask += match[0];
31850                }
31851            }
31852            return mask;
31853        }
31854        function pad(val, len) {
31855            val = String(val);
31856            len = len || 2;
31857            while (val.length < len) {
31858                val = "0" + val;
31859            }
31860            return val;
31861        }
31862        function analyseMask(maskString, format, opts) {
31863            var dateObj = {
31864                date: new Date(1, 0, 1)
31865            }, targetProp, mask = maskString, match, dateOperation, targetValidator;
31866            function extendProperty(value) {
31867                var correctedValue = value.replace(/[^0-9]/g, "0");
31868                if (correctedValue != value) {
31869                    var enteredPart = value.replace(/[^0-9]/g, ""), min = (opts.min && opts.min[targetProp] || value).toString(), max = (opts.max && opts.max[targetProp] || value).toString();
31870                    correctedValue = enteredPart + (enteredPart < min.slice(0, enteredPart.length) ? min.slice(enteredPart.length) : enteredPart > max.slice(0, enteredPart.length) ? max.slice(enteredPart.length) : correctedValue.toString().slice(enteredPart.length));
31871                }
31872                return correctedValue;
31873            }
31874            function setValue(dateObj, value, opts) {
31875                dateObj[targetProp] = extendProperty(value);
31876                dateObj["raw" + targetProp] = value;
31877                if (dateOperation !== undefined) dateOperation.call(dateObj.date, targetProp == "month" ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]);
31878            }
31879            if (typeof mask === "string") {
31880                while (match = getTokenizer(opts).exec(format)) {
31881                    var value = mask.slice(0, match[0].length);
31882                    if (formatCode.hasOwnProperty(match[0])) {
31883                        targetValidator = formatCode[match[0]][0];
31884                        targetProp = formatCode[match[0]][2];
31885                        dateOperation = formatCode[match[0]][1];
31886                        setValue(dateObj, value, opts);
31887                    }
31888                    mask = mask.slice(value.length);
31889                }
31890                return dateObj;
31891            } else if (mask && (typeof mask === "undefined" ? "undefined" : _typeof(mask)) === "object" && mask.hasOwnProperty("date")) {
31892                return mask;
31893            }
31894            return undefined;
31895        }
31896        Inputmask.extendAliases({
31897            datetime: {
31898                mask: function mask(opts) {
31899                    formatCode.S = opts.i18n.ordinalSuffix.join("|");
31900                    opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat;
31901                    opts.displayFormat = formatAlias[opts.displayFormat] || opts.displayFormat || opts.inputFormat;
31902                    opts.outputFormat = formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat;
31903                    opts.placeholder = opts.placeholder !== "" ? opts.placeholder : opts.inputFormat.replace(/[\[\]]/, "");
31904                    opts.regex = parse(opts.inputFormat, undefined, opts);
31905                    return null;
31906                },
31907                placeholder: "",
31908                inputFormat: "isoDateTime",
31909                displayFormat: undefined,
31910                outputFormat: undefined,
31911                min: null,
31912                max: null,
31913                i18n: {
31914                    dayNames: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ],
31915                    monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
31915November", "December" ],
31916                    ordinalSuffix: [ "st", "nd", "rd", "th" ]
31917                },
31918                postValidation: function postValidation(buffer, pos, currentResult, opts) {
31919                    opts.min = analyseMask(opts.min, opts.inputFormat, opts);
31920                    opts.max = analyseMask(opts.max, opts.inputFormat, opts);
31921                    var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts);
31922                    if (result && dateParts.date.getTime() === dateParts.date.getTime()) {
31923                        result = isValidDate(dateParts, result);
31924                        result = result && isDateInRange(dateParts, opts);
31925                    }
31926                    if (pos && result && currentResult.pos !== pos) {
31927                        return {
31928                            buffer: parse(opts.inputFormat, dateParts, opts),
31929                            refreshFromBuffer: {
31930                                start: pos,
31931                                end: currentResult.pos
31932                            }
31933                        };
31934                    }
31935                    return result;
31936                },
31937                onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
31938                    var input = this;
31939                    if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
31940                        var today = new Date(), match, date = "";
31941                        while (match = getTokenizer(opts).exec(opts.inputFormat)) {
31942                            if (match[0].charAt(0) === "d") {
31943                                date += pad(today.getDate(), match[0].length);
31944                            } else if (match[0].charAt(0) === "m") {
31945                                date += pad(today.getMonth() + 1, match[0].length);
31946                            } else if (match[0] === "yyyy") {
31947                                date += today.getFullYear().toString();
31948                            } else if (match[0].charAt(0) === "y") {
31949                                date += pad(today.getYear(), match[0].length);
31950                            }
31951                        }
31952                        input.inputmask._valueSet(date);
31953                        $(input).trigger("setvalue");
31954                    }
31955                },
31956                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
31957                    return parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, true);
31958                },
31959                casing: function casing(elem, test, pos, validPositions) {
31960                    if (test.nativeDef.indexOf("[ap]") == 0) return elem.toLowerCase();
31961                    if (test.nativeDef.indexOf("[AP]") == 0) return elem.toUpperCase();
31962                    return elem;
31963                },
31964                insertMode: false,
31965                shiftPositions: false
31966            }
31967        });
31968        return Inputmask;
31969    });
31970}, function(module, exports, __webpack_require__) {
31971    "use strict";
31972    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
31973    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
31974        return typeof obj;
31975    } : function(obj) {
31976        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
31977    };
31978    (function(factory) {
31979        if (true) {
31980            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 
31981            __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 
31982            __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
31983        } else {}
31984    })(function(Inputmask) {
31985        var $ = Inputmask.dependencyLib;
31986        function autoEscape(txt, opts) {
31987            var escapedTxt = "";
31988            for (var i = 0; i < txt.length; i++) {
31989                if (Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i)) {
31990                    escapedTxt += "\\" + txt.charAt(i);
31991                } else escapedTxt += txt.charAt(i);
31992            }
31993            return escapedTxt;
31994        }
31995        function alignDigits(buffer, digits, opts) {
31996            if (digits > 0) {
31997                var radixPosition = $.inArray(opts.radixPoint, buffer);
31998                if (radixPosition === -1) {
31999                    buffer.push(opts.radixPoint);
32000                    radixPosition = buffer.length - 1;
32001                }
32002                for (var i = 1; i <= digits; i++) {
32003                    buffer[radixPosition + i] = buffer[radixPosition + i] || "0";
32004                }
32005            }
32006            return buffer;
32007        }
32008        Inputmask.extendAliases({
32009            numeric: {
32010                mask: function mask(opts) {
32011                    if (opts.repeat !== 0 && isNaN(opts.integerDigits)) {
32012                        opts.integerDigits = opts.repeat;
32013                    }
32014                    opts.repeat = 0;
32015                    if (opts.groupSeparator === opts.radixPoint && opts.digits && opts.digits !== "0") {
32016                        if (opts.radixPoint === ".") {
32017                            opts.groupSeparator = ",";
32018                        } else if (opts.radixPoint === ",") {
32019                            opts.groupSeparator = ".";
32020                        } else opts.groupSeparator = "";
32021                    }
32022                    if (opts.groupSeparator === " ") {
32023                        opts.skipOptionalPartCharacter = undefined;
32024                    }
32025                    opts.autoGroup = opts.autoGroup && opts.groupSeparator !== "";
32026                    if (opts.autoGroup) {
32027                        if (typeof opts.groupSize == "string" && isFinite(opts.groupSize)) opts.groupSize = parseInt(opts.groupSize);
32028                        if (isFinite(opts.integerDigits)) {
32029                            var seps = Math.floor(opts.integerDigits / opts.groupSize);
32030                            var mod = opts.integerDigits % opts.groupSize;
32031                            opts.integerDigits = parseInt(opts.integerDigits) + (mod === 0 ? seps - 1 : seps);
32032                            if (opts.integerDigits < 1) {
32033                                opts.integerDigits = "*";
32034                            }
32035                        }
32036                    }
32037                    if (opts.placeholder.length > 1) {
32038                        opts.placeholder = opts.placeholder.charAt(0);
32039                    }
32040                    if (opts.positionCaretOnClick === "radixFocus" && opts.placeholder === "" && opts.integerOptional === false) {
32041                        opts.positionCaretOnClick = "lvp";
32042                    }
32043                    opts.definitions[";"] = opts.definitions["~"];
32044                    opts.definitions[";"].definitionSymbol = "~";
32045                    if (opts.numericInput === true) {
32046                        opts.positionCaretOnClick = opts.positionCaretOnClick === "radixFocus" ? "lvp" : opts.positionCaretOnClick;
32047                        opts.digitsOptional = false;
32048                        if (isNaN(opts.digits)) opts.digits = 2;
32049                        opts.decimalProtect = false;
32050                    }
32051                    var mask = "[+]";
32052                    mask += autoEscape(opts.prefix, opts);
32053                    if (opts.integerOptional === true) {
32054                        mask += "~{1," + opts.integerDigits + "}";
32055                    } else mask += "~{" + opts.integerDigits + "}";
32056                    if (opts.digits !== undefined) {
32057                        var radixDef = opts.decimalProtect ? ":" : opts.radixPoint;
32058                        var dq = opts.digits.toString().split(",");
32059                        if (isFinite(dq[0]) && dq[1] && isFinite(dq[1])) {
32060                            mask += radixDef + ";{" + opts.digits + "}";
32061                        } else if (isNaN(opts.digits) || parseInt(opts.digits) > 0) {
32062                            if (opts.digitsOptional) {
32063                                mask += "[" + radixDef + ";{1," + opts.digits + "}]";
32064                            } else mask += radixDef + ";{" + opts.digits + "}";
32065                        }
32066                    }
32067                    mask += autoEscape(opts.suffix, opts);
32068                    mask += "[-]";
32069                    opts.greedy = false;
32070                    return mask;
32071                },
32072                placeholder: "",
32073                greedy: false,
32074                digits: "*",
32075                digitsOptional: true,
32076                enforceDigitsOnBlur: false,
32077                radixPoint: ".",
32078                positionCaretOnClick: "radixFocus",
32079                groupSize: 3,
32080                groupSeparator: "",
32081                autoGroup: false,
32082                allowMinus: true,
32083                negationSymbol: {
32084                    front: "-",
32085                    back: ""
32086                },
32087                integerDigits: "+",
32088                integerOptional: true,
32089                prefix: "",
32090                suffix: "",
32091                rightAlign: true,
32092                decimalProtect: true,
32093                min: null,
32094                max: null,
32095                step: 1,
32096                insertMode: true,
32097                autoUnmask: false,
32098                unmaskAsNumber: false,
32099                inputType: "text",
32100                inputmode: "numeric",
32101                preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset) {
32102                    if (c === "-" || c === opts.negationSymbol.front) {
32103                        if (opts.allowMinus !== true) return false;
32104                        opts.isNegative = opts.isNegative === undefined ? true : !opts.isNegative;
32105                        if (buffer.join("") === "") return true;
32106                        return {
32107                            caret: maskset.validPositions[pos] ? pos : undefined,
32108                            dopost: true
32109                        };
32110                    }
32111                    if (isSelection === false && c === opts.radixPoint && opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0)) {
32112                        var radixPos = $.inArray(opts.radixPoint, buffer);
32113                        if (radixPos !== -1 && maskset.validPositions[radixPos] !== undefined) {
32114                            if (opts.numericInput === true) {
32115                                return pos === radixPos;
32116                            }
32117                            return {
32118                                caret: radixPos + 1
32119                            };
32120                        }
32121                    }
32122                    return true;
32123                },
32124                postValidation: function postValidation(buffer, pos, currentResult, opts) {
32125                    function buildPostMask(buffer, opts) {
32126                        var postMask = "";
32127                        postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}";
32128                        if (opts.radixPoint !== "") {
32129                            var radixSplit = buffer.join("").split(opts.radixPoint);
32130                            if (radixSplit[1]) {
32131                                postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}";
32132                            }
32133                        }
32134                        return postMask;
32135                    }
32136                    var suffix = opts.suffix.split(""), prefix = opts.prefix.split("");
32137                    if (currentResult.pos === undefined && currentResult.caret !== undefined && currentResult.dopost !== true) return currentResult;
32138                    var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos;
32139                    var maskedValue = buffer.slice();
32140                    if (opts.numericInput) {
32141                        caretPos = maskedValue.length - caretPos - 1;
32142                        maskedValue = maskedValue.reverse();
32143                    }
32144                    var charAtPos = maskedValue[caretPos];
32145                    if (charAtPos === opts.groupSeparator) {
32146                        caretPos += 1;
32147                        charAtPos = maskedValue[caretPos];
32148                    }
32149                    if (caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult;
32150                    if (charAtPos !== undefined) {
32151                        if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) {
32152                            maskedValue[caretPos] = "?";
32153                            if (opts.prefix.length > 0 && caretPos >= (opts.isNegative === false ? 1 : 0) && caretPos < opts.prefix.length - 1 + (opts.isNegative === false ? 1 : 0)) {
32154                                prefix[caretPos - (opts.isNegative === false ? 1 : 0)] = "?";
32155                            } else if (opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0)) {
32156                                suffix[caretPos - (maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0))] = "?";
32157                            }
32158                        }
32159                    }
32160                    prefix = prefix.join("");
32161                    suffix = suffix.join("");
32162                    var processValue = maskedValue.join("").replace(prefix, "");
32163                    processValue = processValue.replace(suffix, "");
32164                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
32165                    processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "");
32166                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
32167                    if (isNaN(opts.placeholder)) {
32168                        processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), "");
32169                    }
32170                    if (processValue.length > 1 && processValue.indexOf(opts.radixPoint) !== 1) {
32171                        if (charAtPos === "0") {
32172                            processValue = processValue.replace(/^\?/g, "");
32173                        }
32174                        processValue = processValue.replace(/^0/g, "");
32175                    }
32176                    if (processValue.charAt(0) === opts.radixPoint && opts.radixPoint !== "" && opts.numericInput !== true) {
32177                        processValue = "0" + processValue;
32178                    }
32179                    if (processValue !== "") {
32180                        processValue = processValue.split("");
32181                        if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && isFinite(opts.digits)) {
32182                            var radixPosition = $.inArray(opts.radixPoint, processValue);
32183                            var rpb = $.inArray(opts.radixPoint, maskedValue);
32184                            if (radixPosition === -1) {
32185                                processValue.push(opts.radixPoint);
32186                                radixPosition = processValue.length - 1;
32187                            }
32188                            for (var i = 1; i <= opts.digits; i++) {
32189                                if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && (processValue[radixPosition + i] === undefined || processValue[radixPosition + i] === opts.placeholder.charAt(0))) {
32190                                    processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0);
32191                                } else if (rpb !== -1 && maskedValue[rpb + i] !== undefined) {
32192                                    processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i];
32193                                }
32194                            }
32195                        }
32196                        if (opts.autoGroup === true && opts.groupSeparator !== "" && (charAtPos !== opts.radixPoint || currentResult.pos !== undefined || currentResult.dopost)) {
32197                            var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint;
32198                            processValue = Inputmask(buildPostMask(processValue, opts), {
32199                                numericInput: true,
32200                                jitMasking: true,
32201                                definitions: {
32202                                    "*": {
32203                                        validator: "[0-9?]",
32204                                        cardinality: 1
32205                                    }
32206                                }
32207                            }).format(processValue.join(""));
32208                            if (addRadix) processValue += opts.radixPoint;
32209                            if (processValue.charAt(0) === opts.groupSeparator) {
32210                                processValue.substr(1);
32211                            }
32212                        } else processValue = processValue.join("");
32213                    }
32214                    if (opts.isNegative && currentResult.event === "blur") {
32215                        opts.isNegative = processValue !== "0";
32216                    }
32217                    processValue = prefix + processValue;
32218                    processValue += suffix;
32219                    if (opts.isNegative) {
32220                        processValue = opts.negationSymbol.front + processValue;
32221                        processValue += opts.negationSymbol.back;
32222                    }
32223                    processValue = processValue.split("");
32224                    if (charAtPos !== undefined) {
32225                        if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) {
32226                            caretPos = $.inArray("?", processValue);
32227                            if (caretPos > -1) {
32228                                processValue[caretPos] = charAtPos;
32229                            } else caretPos = currentResult.caret || 0;
32230                        } else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) {
32231                            var newCaretPos = $.inArray(charAtPos, processValue);
32232                            if (newCaretPos !== -1) caretPos = newCaretPos;
32233                        }
32234                    }
32235                    if (opts.numericInput) {
32236                        caretPos = processValue.length - caretPos - 1;
32237                        processValue = processValue.reverse();
32238                    }
32239                    var rslt = {
32240                        caret: (charAtPos === undefined || currentResult.pos !== undefined) && caretPos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos,
32241                        buffer: processValue,
32242                        refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("")
32243                    };
32244                    return rslt.refreshFromBuffer ? rslt : currentResult;
32245                },
32246                onBeforeWrite: function onBeforeWrite(e, buffer, caretPos, opts) {
32247                    function parseMinMaxOptions(opts) {
32248                        if (opts.parseMinMaxOptions === undefined) {
32249                            if (opts.min !== null) {
32250                                opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
32251                                if (opts.radixPoint === ",") opts.min = opts.min.replace(opts.radixPoint, ".");
32252                                opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN;
32253                                if (isNaN(opts.min)) opts.min = Number.MIN_VALUE;
32254                            }
32255                            if (opts.max !== null) {
32256                                opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
32257                                if (opts.radixPoint === ",") opts.max = opts.max.replace(opts.radixPoint, ".");
32258                                opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN;
32259                                if (isNaN(opts.max)) opts.max = Number.MAX_VALUE;
32260                            }
32261                            opts.parseMinMaxOptions = "done";
32262                        }
32263                    }
32264                    if (e) {
32265                        switch (e.type) {
32266                          case "keydown":
32267                            return opts.postValidation(buffer, caretPos, {
32268                                caret: caretPos,
32269                                dopost: true
32270                            }, opts);
32271
32272                          case "blur":
32273                          case "checkval":
32274                            var unmasked;
32275                            parseMinMaxOptions(opts);
32276                            if (opts.min !== null || opts.max !== null) {
32277                                unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, {
32278                                    unmaskAsNumber: true
32279                                }));
32280                                if (opts.min !== null && unmasked < opts.min) {
32281                                    opts.isNegative = opts.min < 0;
32282                                    return opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), caretPos, {
32283                                        caret: caretPos,
32284                                        dopost: true,
32285                                        placeholder: "0"
32286                                    }, opts);
32287                                } else if (opts.max !== null && unmasked > opts.max) {
32288                                    opts.isNegative = opts.max < 0;
32289                                    return opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), caretPos, {
32290                                        caret: caretPos,
32291                                        dopost: true,
32292                                        placeholder: "0"
32293                                    }, opts);
32294                                }
32295                            }
32296                            return opts.postValidation(buffer, caretPos, {
32297                                caret: caretPos,
32298                                placeholder: "0",
32299                                event: "blur"
32300                            }, opts);
32301
32302                          case "_checkval":
32303                            return {
32304                                caret: caretPos
32305                            };
32306
32307                          default:
32308                            break;
32309                        }
32310                    }
32311                },
32312                regex: {
32313                    integerPart: function integerPart(opts, emptyCheck) {
32314                        return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
32315                    },
32316                    integerNPart: function integerNPart(opts) {
32317                        return new RegExp("[\\d" + Inputmask.escapeRegex(opts.
32317groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+");
32318                    }
32319                },
32320                definitions: {
32321                    "~": {
32322                        validator: function validator(chrs, maskset, pos, strict, opts, isSelection) {
32323                            var isValid, l;
32324                            if (chrs === "k" || chrs === "m") {
32325                                isValid = {
32326                                    insert: [],
32327                                    c: 0
32328                                };
32329                                for (var i = 0, l = chrs === "k" ? 2 : 5; i < l; i++) {
32330                                    isValid.insert.push({
32331                                        pos: pos + i,
32332                                        c: 0
32333                                    });
32334                                }
32335                                isValid.pos = pos + l;
32336                                return isValid;
32337                            }
32338                            isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs);
32339                            if (isValid === true) {
32340                                if (opts.numericInput !== true && maskset.validPositions[pos] !== undefined && maskset.validPositions[pos].match.def === "~" && !isSelection) {
32341                                    var processValue = maskset.buffer.join("");
32342                                    processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "");
32343                                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
32344                                    var pvRadixSplit = processValue.split(opts.radixPoint);
32345                                    if (pvRadixSplit.length > 1) {
32346                                        pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0));
32347                                    }
32348                                    if (pvRadixSplit[0] === "0") {
32349                                        pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0));
32350                                    }
32351                                    processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || "";
32352                                    var bufferTemplate = maskset._buffer.join("");
32353                                    if (processValue === opts.radixPoint) {
32354                                        processValue = bufferTemplate;
32355                                    }
32356                                    while (processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$") === null) {
32357                                        bufferTemplate = bufferTemplate.slice(1);
32358                                    }
32359                                    processValue = processValue.replace(bufferTemplate, "");
32360                                    processValue = processValue.split("");
32361                                    if (processValue[pos] === undefined) {
32362                                        isValid = {
32363                                            pos: pos,
32364                                            remove: pos
32365                                        };
32366                                    } else {
32367                                        isValid = {
32368                                            pos: pos
32369                                        };
32370                                    }
32371                                }
32372                            } else if (!strict && chrs === opts.radixPoint && maskset.validPositions[pos - 1] === undefined) {
32373                                isValid = {
32374                                    insert: {
32375                                        pos: pos,
32376                                        c: 0
32377                                    },
32378                                    pos: pos + 1
32379                                };
32380                            }
32381                            return isValid;
32382                        },
32383                        cardinality: 1
32384                    },
32385                    "+": {
32386                        validator: function validator(chrs, maskset, pos, strict, opts) {
32387                            return opts.allowMinus && (chrs === "-" || chrs === opts.negationSymbol.front);
32388                        },
32389                        cardinality: 1,
32390                        placeholder: ""
32391                    },
32392                    "-": {
32393                        validator: function validator(chrs, maskset, pos, strict, opts) {
32394                            return opts.allowMinus && chrs === opts.negationSymbol.back;
32395                        },
32396                        cardinality: 1,
32397                        placeholder: ""
32398                    },
32399                    ":": {
32400                        validator: function validator(chrs, maskset, pos, strict, opts) {
32401                            var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]";
32402                            var isValid = new RegExp(radix).test(chrs);
32403                            if (isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint) {
32404                                isValid = {
32405                                    caret: pos + 1
32406                                };
32407                            }
32408                            return isValid;
32409                        },
32410                        cardinality: 1,
32411                        placeholder: function placeholder(opts) {
32412                            return opts.radixPoint;
32413                        }
32414                    }
32415                },
32416                onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) {
32417                    if (unmaskedValue === "" && opts.nullable === true) {
32418                        return unmaskedValue;
32419                    }
32420                    var processValue = maskedValue.replace(opts.prefix, "");
32421                    processValue = processValue.replace(opts.suffix, "");
32422                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
32423                    if (opts.placeholder.charAt(0) !== "") {
32424                        processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0");
32425                    }
32426                    if (opts.unmaskAsNumber) {
32427                        if (opts.radixPoint !== "" && processValue.indexOf(opts.radixPoint) !== -1) processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), ".");
32428                        processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-");
32429                        processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
32430                        return Number(processValue);
32431                    }
32432                    return processValue;
32433                },
32434                isComplete: function isComplete(buffer, opts) {
32435                    var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join("");
32436                    maskedValue = maskedValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-");
32437                    maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
32438                    maskedValue = maskedValue.replace(opts.prefix, "");
32439                    maskedValue = maskedValue.replace(opts.suffix, "");
32440                    maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator) + "([0-9]{3})", "g"), "$1");
32441                    if (opts.radixPoint === ",") maskedValue = maskedValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".");
32442                    return isFinite(maskedValue);
32443                },
32444                onBeforeMask: function onBeforeMask(initialValue, opts) {
32445                    opts.isNegative = undefined;
32446                    var radixPoint = opts.radixPoint || ",";
32447                    if ((typeof initialValue == "number" || opts.inputType === "number") && radixPoint !== "") {
32448                        initialValue = initialValue.toString().replace(".", radixPoint);
32449                    }
32450                    var valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = valueParts.length > 1 ? valueParts[1].replace(/[^0-9]/g, "") : "";
32451                    initialValue = integerPart + (decimalPart !== "" ? radixPoint + decimalPart : decimalPart);
32452                    var digits = 0;
32453                    if (radixPoint !== "") {
32454                        digits = decimalPart.length;
32455                        if (decimalPart !== "") {
32456                            var digitsFactor = Math.pow(10, digits || 1);
32457                            if (isFinite(opts.digits)) {
32458                                digits = parseInt(opts.digits);
32459                                digitsFactor = Math.pow(10, digits);
32460                            }
32461                            initialValue = initialValue.replace(Inputmask.escapeRegex(radixPoint), ".");
32462                            if (isFinite(initialValue)) initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor;
32463                            initialValue = initialValue.toString().replace(".", radixPoint);
32464                        }
32465                    }
32466                    if (opts.digits === 0 && initialValue.indexOf(Inputmask.escapeRegex(radixPoint)) !== -1) {
32467                        initialValue = initialValue.substring(0, initialValue.indexOf(Inputmask.escapeRegex(radixPoint)));
32468                    }
32469                    return alignDigits(initialValue.toString().split(""), digits, opts).join("");
32470                },
32471                onKeyDown: function onKeyDown(e, buffer, caretPos, opts) {
32472                    var $input = $(this);
32473                    if (e.ctrlKey) {
32474                        switch (e.keyCode) {
32475                          case Inputmask.keyCode.UP:
32476                            $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step));
32477                            $input.trigger("setvalue");
32478                            break;
32479
32480                          case Inputmask.keyCode.DOWN:
32481                            $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step));
32482                            $input.trigger("setvalue");
32483                            break;
32484                        }
32485                    }
32486                }
32487            },
32488            currency: {
32489                prefix: "$ ",
32490                groupSeparator: ",",
32491                alias: "numeric",
32492                placeholder: "0",
32493                autoGroup: true,
32494                digits: 2,
32495                digitsOptional: false,
32496                clearMaskOnLostFocus: false
32497            },
32498            decimal: {
32499                alias: "numeric"
32500            },
32501            integer: {
32502                alias: "numeric",
32503                digits: 0,
32504                radixPoint: ""
32505            },
32506            percentage: {
32507                alias: "numeric",
32508                digits: 2,
32509                digitsOptional: true,
32510                radixPoint: ".",
32511                placeholder: "0",
32512                autoGroup: false,
32513                min: 0,
32514                max: 100,
32515                suffix: " %",
32516                allowMinus: false
32517            }
32518        });
32519        return Inputmask;
32520    });
32521}, function(module, exports, __webpack_require__) {
32522    "use strict";
32523    var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
32524    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
32525        return typeof obj;
32526    } : function(obj) {
32527        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
32528    };
32529    (function(factory) {
32530        if (true) {
32531            !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(4), __webpack_require__(2) ], 
32532            __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__, 
32533            __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
32534        } else {}
32535    })(function($, Inputmask) {
32536        if ($.fn.inputmask === undefined) {
32537            $.fn.inputmask = function(fn, options) {
32538                var nptmask, input = this[0];
32539                if (options === undefined) options = {};
32540                if (typeof fn === "string") {
32541                    switch (fn) {
32542                      case "unmaskedvalue":
32543                        return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val();
32544
32545                      case "remove":
32546                        return this.each(function() {
32547                            if (this.inputmask) this.inputmask.remove();
32548                        });
32549
32550                      case "getemptymask":
32551                        return input && input.inputmask ? input.inputmask.getemptymask() : "";
32552
32553                      case "hasMaskedValue":
32554                        return input && input.inputmask ? input.inputmask.hasMaskedValue() : false;
32555
32556                      case "isComplete":
32557                        return input && input.inputmask ? input.inputmask.isComplete() : true;
32558
32559                      case "getmetadata":
32560                        return input && input.inputmask ? input.inputmask.getmetadata() : undefined;
32561
32562                      case "setvalue":
32563                        Inputmask.setValue(input, options);
32564                        break;
32565
32566                      case "option":
32567                        if (typeof options === "string") {
32568                            if (input && input.inputmask !== undefined) {
32569                                return input.inputmask.option(options);
32570                            }
32571                        } else {
32572                            return this.each(function() {
32573                                if (this.inputmask !== undefined) {
32574                                    return this.inputmask.option(options);
32575                                }
32576                            });
32577                        }
32578                        break;
32579
32580                      default:
32581                        options.alias = fn;
32582                        nptmask = new Inputmask(options);
32583                        return this.each(function() {
32584                            nptmask.mask(this);
32585                        });
32586                    }
32587                } else if (Array.isArray(fn)) {
32588                    options.alias = fn;
32589                    nptmask = new Inputmask(options);
32590                    return this.each(function() {
32591                        nptmask.mask(this);
32592                    });
32593                } else if ((typeof fn === "undefined" ? "undefined" : _typeof(fn)) == "object") {
32594                    nptmask = new Inputmask(fn);
32595                    if (fn.mask === undefined && fn.alias === undefined) {
32596                        return this.each(function() {
32597                            if (this.inputmask !== undefined) {
32598                                return this.inputmask.option(fn);
32599                            } else nptmask.mask(this);
32600                        });
32601                    } else {
32602                        return this.each(function() {
32603                            nptmask.mask(this);
32604                        });
32605                    }
32606                } else if (fn === undefined) {
32607                    return this.each(function() {
32608                        nptmask = new Inputmask(options);
32609                        nptmask.mask(this);
32610                    });
32611                }
32612            };
32613        }
32614        return $.fn.inputmask;
32615    });
32616} ]);
32617/*!
32618* inputmask.date.extensions.js
32619* https://github.com/RobinHerbots/Inputmask
32620* Copyright (c) 2010 - 2019 Robin Herbots
32621* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
32622* Version: 4.0.8
32623*/
32624
32625(function(factory) {
32626    if (typeof define === "function" && define.amd) {
32627        define([ "./inputmask" ], factory);
32628    } else if (typeof exports === "object") {
32629        module.exports = factory(require("./inputmask"));
32630    } else {
32631        factory(window.Inputmask);
32632    }
32633})(function(Inputmask) {
32634    var $ = Inputmask.dependencyLib;
32635    var formatCode = {
32636        d: [ "[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", Date.prototype.getDate ],
32637        dd: [ "0[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", function() {
32638            return pad(Date.prototype.getDate.call(this), 2);
32639        } ],
32640        ddd: [ "" ],
32641        dddd: [ "" ],
32642        m: [ "[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
32643            return Date.prototype.getMonth.call(this) + 1;
32644        } ],
32645        mm: [ "0[1-9]|1[012]", Date.prototype.setMonth, "month", function() {
32646            return pad(Date.prototype.getMonth.call(this) + 1, 2);
32647        } ],
32648        mmm: [ "" ],
32649        mmmm: [ "" ],
32650        yy: [ "[0-9]{2}", Date.prototype.setFullYear, "year", function() {
32651            return pad(Date.prototype.getFullYear.call(this), 2);
32652        } ],
32653        yyyy: [ "[0-9]{4}", Date.prototype.setFullYear, "year", function() {
32654            return pad(Date.prototype.getFullYear.call(this), 4);
32655        } ],
32656        h: [ "[1-9]|1[0-2]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
32657        hh: [ "0[1-9]|1[0-2]", Date.prototype.setHours, "hours", function() {
32658            return pad(Date.prototype.getHours.call(this), 2);
32659        } ],
32660        hhh: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ],
32661        H: [ "1?[0-9]|2[0-3]", Date.prototype.setHours, "hours", Date.prototype.getHours ],
32662        HH: [ "0[0-9]|1[0-9]|2[0-3]", Date.prototype.setHours, "hours", function() {
32663            return pad(Date.prototype.getHours.call(this), 2);
32664        } ],
32665        HHH: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ],
32666        M: [ "[1-5]?[0-9]", Date.prototype.setMinutes, "minutes", Date.prototype.getMinutes ],
32667        MM: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setMinutes, "minutes", function() {
32668            return pad(Date.prototype.getMinutes.call(this), 2);
32669        } ],
32670        ss: [ "[0-5][0-9]", Date.prototype.setSeconds, "seconds", function() {
32671            return pad(Date.prototype.getSeconds.call(this), 2);
32672        } ],
32673        l: [ "[0-9]{3}", Date.prototype.setMilliseconds, "milliseconds", function() {
32674            return pad(Date.prototype.getMilliseconds.call(this), 3);
32675        } ],
32676        L: [ "[0-9]{2}", Date.prototype.setMilliseconds, "milliseconds", function() {
32677            return pad(Date.prototype.getMilliseconds.call(this), 2);
32678        } ],
32679        t: [ "[ap]" ],
32680        tt: [ "[ap]m" ],
32681        T: [ "[AP]" ],
32682        TT: [ "[AP]M" ],
32683        Z: [ "" ],
32684        o: [ "" ],
32685        S: [ "" ]
32686    }, formatAlias = {
32687        isoDate: "yyyy-mm-dd",
32688        isoTime: "HH:MM:ss",
32689        isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
32690        isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
32691    };
32692    function getTokenizer(opts) {
32693        if (!opts.tokenizer) {
32694            var tokens = [];
32695            for (var ndx in formatCode) {
32696                if (tokens.indexOf(ndx[0]) === -1) tokens.push(ndx[0]);
32697            }
32698            opts.tokenizer = "(" + tokens.join("+|") + ")+?|.";
32699            opts.tokenizer = new RegExp(opts.tokenizer, "g");
32700        }
32701        return opts.tokenizer;
32702    }
32703    function isValidDate(dateParts, currentResult) {
32704        return !isFinite(dateParts.rawday) || dateParts.day == "29" && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day ? currentResult : false;
32705    }
32706    function isDateInRange(dateParts, opts) {
32707        var result = true;
32708        if (opts.min) {
32709            if (dateParts["rawyear"]) {
32710                var rawYear = dateParts["rawyear"].replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length);
32711                result = minYear <= rawYear;
32712            }
32713            if (dateParts["year"] === dateParts["rawyear"]) {
32714                if (opts.min.date.getTime() === opts.min.date.getTime()) {
32715                    result = opts.min.date.getTime() <= dateParts.date.getTime();
32716                }
32717            }
32718        }
32719        if (result && opts.max && opts.max.date.getTime() === opts.max.date.getTime()) {
32720            result = opts.max.date.getTime() >= dateParts.date.getTime();
32721        }
32722        return result;
32723    }
32724    function parse(format, dateObjValue, opts, raw) {
32725        var mask = "", match;
32726        while (match = getTokenizer(opts).exec(format)) {
32727            if (dateObjValue === undefined) {
32728                if (formatCode[match[0]]) {
32729                    mask += "(" + formatCode[match[0]][0] + ")";
32730                } else {
32731                    switch (match[0]) {
32732                      case "[":
32733                        mask += "(";
32734                        break;
32735
32736                      case "]":
32737                        mask += ")?";
32738                        break;
32739
32740                      default:
32741                        mask += Inputmask.escapeRegex(match[0]);
32742                    }
32743                }
32744            } else {
32745                if (formatCode[match[0]]) {
32746                    if (raw !== true && formatCode[match[0]][3]) {
32747                        var getFn = formatCode[match[0]][3];
32748                        mask += getFn.call(dateObjValue.date);
32749                    } else if (formatCode[match[0]][2]) mask += dateObjValue["raw" + formatCode[match[0]][2]]; else mask += match[0];
32750                } else mask += match[0];
32751            }
32752        }
32753        return mask;
32754    }
32755    function pad(val, len) {
32756        val = String(val);
32757        len = len || 2;
32758        while (val.length < len) val = "0" + val;
32759        return val;
32760    }
32761    function analyseMask(maskString, format, opts) {
32762        var dateObj = {
32763            date: new Date(1, 0, 1)
32764        }, targetProp, mask = maskString, match, dateOperation, targetValidator;
32765        function extendProperty(value) {
32766            var correctedValue = value.replace(/[^0-9]/g, "0");
32767            if (correctedValue != value) {
32768                var enteredPart = value.replace(/[^0-9]/g, ""), min = (opts.min && opts.min[targetProp] || value).toString(), max = (opts.max && opts.max[targetProp] || value).toString();
32769                correctedValue = enteredPart + (enteredPart < min.slice(0, enteredPart.length) ? min.slice(enteredPart.length) : enteredPart > max.slice(0, enteredPart.length) ? max.slice(enteredPart.length) : correctedValue.toString().slice(enteredPart.length));
32770            }
32771            return correctedValue;
32772        }
32773        function setValue(dateObj, value, opts) {
32774            dateObj[targetProp] = extendProperty(value);
32775            dateObj["raw" + targetProp] = value;
32776            if (dateOperation !== undefined) dateOperation.call(dateObj.date, targetProp == "month" ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]);
32777        }
32778        if (typeof mask === "string") {
32779            while (match = getTokenizer(opts).exec(format)) {
32780                var value = mask.slice(0, match[0].length);
32781                if (formatCode.hasOwnProperty(match[0])) {
32782                    targetValidator = formatCode[match[0]][0];
32783                    targetProp = formatCode[match[0]][2];
32784                    dateOperation = formatCode[match[0]][1];
32785                    setValue(dateObj, value, opts);
32786                }
32787                mask = mask.slice(value.length);
32788            }
32789            return dateObj;
32790        } else if (mask && typeof mask === "object" && mask.hasOwnProperty("date")) {
32791            return mask;
32792        }
32793        return undefined;
32794    }
32795    Inputmask.extendAliases({
32796        datetime: {
32797            mask: function(opts) {
32798                formatCode.S = opts.i18n.ordinalSuffix.join("|");
32799                opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat;
32800                opts.displayFormat = formatAlias[opts.displayFormat] || opts.displayFormat || opts.inputFormat;
32801                opts.outputFormat = formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat;
32802                opts.placeholder = opts.placeholder !== "" ? opts.placeholder : opts.inputFormat.replace(/[\[\]]/, "");
32803                opts.regex = parse(opts.inputFormat, undefined, opts);
32804                return null;
32805            },
32806            placeholder: "",
32807            inputFormat: "isoDateTime",
32808            displayFormat: undefined,
32809            outputFormat: undefined,
32810            min: null,
32811            max: null,
32812            i18n: {
32813                dayNames: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ],
32814                monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
32814November", "December" ],
32815                ordinalSuffix: [ "st", "nd", "rd", "th" ]
32816            },
32817            postValidation: function(buffer, pos, currentResult, opts) {
32818                opts.min = analyseMask(opts.min, opts.inputFormat, opts);
32819                opts.max = analyseMask(opts.max, opts.inputFormat, opts);
32820                var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts);
32821                if (result && dateParts.date.getTime() === dateParts.date.getTime()) {
32822                    result = isValidDate(dateParts, result);
32823                    result = result && isDateInRange(dateParts, opts);
32824                }
32825                if (pos && result && currentResult.pos !== pos) {
32826                    return {
32827                        buffer: parse(opts.inputFormat, dateParts, opts),
32828                        refreshFromBuffer: {
32829                            start: pos,
32830                            end: currentResult.pos
32831                        }
32832                    };
32833                }
32834                return result;
32835            },
32836            onKeyDown: function(e, buffer, caretPos, opts) {
32837                var input = this;
32838                if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) {
32839                    var today = new Date(), match, date = "";
32840                    while (match = getTokenizer(opts).exec(opts.inputFormat)) {
32841                        if (match[0].charAt(0) === "d") {
32842                            date += pad(today.getDate(), match[0].length);
32843                        } else if (match[0].charAt(0) === "m") {
32844                            date += pad(today.getMonth() + 1, match[0].length);
32845                        } else if (match[0] === "yyyy") {
32846                            date += today.getFullYear().toString();
32847                        } else if (match[0].charAt(0) === "y") {
32848                            date += pad(today.getYear(), match[0].length);
32849                        }
32850                    }
32851                    input.inputmask._valueSet(date);
32852                    $(input).trigger("setvalue");
32853                }
32854            },
32855            onUnMask: function(maskedValue, unmaskedValue, opts) {
32856                return parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, true);
32857            },
32858            casing: function(elem, test, pos, validPositions) {
32859                if (test.nativeDef.indexOf("[ap]") == 0) return elem.toLowerCase();
32860                if (test.nativeDef.indexOf("[AP]") == 0) return elem.toUpperCase();
32861                return elem;
32862            },
32863            insertMode: false,
32864            shiftPositions: false
32865        }
32866    });
32867    return Inputmask;
32868});
32869/*!
32870* inputmask.numeric.extensions.js
32871* https://github.com/RobinHerbots/Inputmask
32872* Copyright (c) 2010 - 2019 Robin Herbots
32873* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
32874* Version: 4.0.8
32875*/
32876
32877(function(factory) {
32878    if (typeof define === "function" && define.amd) {
32879        define([ "./inputmask" ], factory);
32880    } else if (typeof exports === "object") {
32881        module.exports = factory(require("./inputmask"));
32882    } else {
32883        factory(window.Inputmask);
32884    }
32885})(function(Inputmask) {
32886    var $ = Inputmask.dependencyLib;
32887    function autoEscape(txt, opts) {
32888        var escapedTxt = "";
32889        for (var i = 0; i < txt.length; i++) {
32890            if (Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i)) {
32891                escapedTxt += "\\" + txt.charAt(i);
32892            } else escapedTxt += txt.charAt(i);
32893        }
32894        return escapedTxt;
32895    }
32896    function alignDigits(buffer, digits, opts) {
32897        if (digits > 0) {
32898            var radixPosition = $.inArray(opts.radixPoint, buffer);
32899            if (radixPosition === -1) {
32900                buffer.push(opts.radixPoint);
32901                radixPosition = buffer.length - 1;
32902            }
32903            for (var i = 1; i <= digits; i++) {
32904                buffer[radixPosition + i] = buffer[radixPosition + i] || "0";
32905            }
32906        }
32907        return buffer;
32908    }
32909    Inputmask.extendAliases({
32910        numeric: {
32911            mask: function(opts) {
32912                if (opts.repeat !== 0 && isNaN(opts.integerDigits)) {
32913                    opts.integerDigits = opts.repeat;
32914                }
32915                opts.repeat = 0;
32916                if (opts.groupSeparator === opts.radixPoint && opts.digits && opts.digits !== "0") {
32917                    if (opts.radixPoint === ".") {
32918                        opts.groupSeparator = ",";
32919                    } else if (opts.radixPoint === ",") {
32920                        opts.groupSeparator = ".";
32921                    } else opts.groupSeparator = "";
32922                }
32923                if (opts.groupSeparator === " ") {
32924                    opts.skipOptionalPartCharacter = undefined;
32925                }
32926                opts.autoGroup = opts.autoGroup && opts.groupSeparator !== "";
32927                if (opts.autoGroup) {
32928                    if (typeof opts.groupSize == "string" && isFinite(opts.groupSize)) opts.groupSize = parseInt(opts.groupSize);
32929                    if (isFinite(opts.integerDigits)) {
32930                        var seps = Math.floor(opts.integerDigits / opts.groupSize);
32931                        var mod = opts.integerDigits % opts.groupSize;
32932                        opts.integerDigits = parseInt(opts.integerDigits) + (mod === 0 ? seps - 1 : seps);
32933                        if (opts.integerDigits < 1) {
32934                            opts.integerDigits = "*";
32935                        }
32936                    }
32937                }
32938                if (opts.placeholder.length > 1) {
32939                    opts.placeholder = opts.placeholder.charAt(0);
32940                }
32941                if (opts.positionCaretOnClick === "radixFocus" && (opts.placeholder === "" && opts.integerOptional === false)) {
32942                    opts.positionCaretOnClick = "lvp";
32943                }
32944                opts.definitions[";"] = opts.definitions["~"];
32945                opts.definitions[";"].definitionSymbol = "~";
32946                if (opts.numericInput === true) {
32947                    opts.positionCaretOnClick = opts.positionCaretOnClick === "radixFocus" ? "lvp" : opts.positionCaretOnClick;
32948                    opts.digitsOptional = false;
32949                    if (isNaN(opts.digits)) opts.digits = 2;
32950                    opts.decimalProtect = false;
32951                }
32952                var mask = "[+]";
32953                mask += autoEscape(opts.prefix, opts);
32954                if (opts.integerOptional === true) {
32955                    mask += "~{1," + opts.integerDigits + "}";
32956                } else mask += "~{" + opts.integerDigits + "}";
32957                if (opts.digits !== undefined) {
32958                    var radixDef = opts.decimalProtect ? ":" : opts.radixPoint;
32959                    var dq = opts.digits.toString().split(",");
32960                    if (isFinite(dq[0]) && dq[1] && isFinite(dq[1])) {
32961                        mask += radixDef + ";{" + opts.digits + "}";
32962                    } else if (isNaN(opts.digits) || parseInt(opts.digits) > 0) {
32963                        if (opts.digitsOptional) {
32964                            mask += "[" + radixDef + ";{1," + opts.digits + "}]";
32965                        } else mask += radixDef + ";{" + opts.digits + "}";
32966                    }
32967                }
32968                mask += autoEscape(opts.suffix, opts);
32969                mask += "[-]";
32970                opts.greedy = false;
32971                return mask;
32972            },
32973            placeholder: "",
32974            greedy: false,
32975            digits: "*",
32976            digitsOptional: true,
32977            enforceDigitsOnBlur: false,
32978            radixPoint: ".",
32979            positionCaretOnClick: "radixFocus",
32980            groupSize: 3,
32981            groupSeparator: "",
32982            autoGroup: false,
32983            allowMinus: true,
32984            negationSymbol: {
32985                front: "-",
32986                back: ""
32987            },
32988            integerDigits: "+",
32989            integerOptional: true,
32990            prefix: "",
32991            suffix: "",
32992            rightAlign: true,
32993            decimalProtect: true,
32994            min: null,
32995            max: null,
32996            step: 1,
32997            insertMode: true,
32998            autoUnmask: false,
32999            unmaskAsNumber: false,
33000            inputType: "text",
33001            inputmode: "numeric",
33002            preValidation: function(buffer, pos, c, isSelection, opts, maskset) {
33003                if (c === "-" || c === opts.negationSymbol.front) {
33004                    if (opts.allowMinus !== true) return false;
33005                    opts.isNegative = opts.isNegative === undefined ? true : !opts.isNegative;
33006                    if (buffer.join("") === "") return true;
33007                    return {
33008                        caret: maskset.validPositions[pos] ? pos : undefined,
33009                        dopost: true
33010                    };
33011                }
33012                if (isSelection === false && c === opts.radixPoint && (opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0))) {
33013                    var radixPos = $.inArray(opts.radixPoint, buffer);
33014                    if (radixPos !== -1 && maskset.validPositions[radixPos] !== undefined) {
33015                        if (opts.numericInput === true) {
33016                            return pos === radixPos;
33017                        }
33018                        return {
33019                            caret: radixPos + 1
33020                        };
33021                    }
33022                }
33023                return true;
33024            },
33025            postValidation: function(buffer, pos, currentResult, opts) {
33026                function buildPostMask(buffer, opts) {
33027                    var postMask = "";
33028                    postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}";
33029                    if (opts.radixPoint !== "") {
33030                        var radixSplit = buffer.join("").split(opts.radixPoint);
33031                        if (radixSplit[1]) {
33032                            postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}";
33033                        }
33034                    }
33035                    return postMask;
33036                }
33037                var suffix = opts.suffix.split(""), prefix = opts.prefix.split("");
33038                if (currentResult.pos === undefined && currentResult.caret !== undefined && currentResult.dopost !== true) return currentResult;
33039                var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos;
33040                var maskedValue = buffer.slice();
33041                if (opts.numericInput) {
33042                    caretPos = maskedValue.length - caretPos - 1;
33043                    maskedValue = maskedValue.reverse();
33044                }
33045                var charAtPos = maskedValue[caretPos];
33046                if (charAtPos === opts.groupSeparator) {
33047                    caretPos += 1;
33048                    charAtPos = maskedValue[caretPos];
33049                }
33050                if (caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult;
33051                if (charAtPos !== undefined) {
33052                    if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) {
33053                        maskedValue[caretPos] = "?";
33054                        if (opts.prefix.length > 0 && caretPos >= (opts.isNegative === false ? 1 : 0) && caretPos < opts.prefix.length - 1 + (opts.isNegative === false ? 1 : 0)) {
33055                            prefix[caretPos - (opts.isNegative === false ? 1 : 0)] = "?";
33056                        } else if (opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0)) {
33057                            suffix[caretPos - (maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0))] = "?";
33058                        }
33059                    }
33060                }
33061                prefix = prefix.join("");
33062                suffix = suffix.join("");
33063                var processValue = maskedValue.join("").replace(prefix, "");
33064                processValue = processValue.replace(suffix, "");
33065                processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
33066                processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "");
33067                processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
33068                if (isNaN(opts.placeholder)) {
33069                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), "");
33070                }
33071                if (processValue.length > 1 && processValue.indexOf(opts.radixPoint) !== 1) {
33072                    if (charAtPos === "0") {
33073                        processValue = processValue.replace(/^\?/g, "");
33074                    }
33075                    processValue = processValue.replace(/^0/g, "");
33076                }
33077                if (processValue.charAt(0) === opts.radixPoint && opts.radixPoint !== "" && opts.numericInput !== true) {
33078                    processValue = "0" + processValue;
33079                }
33080                if (processValue !== "") {
33081                    processValue = processValue.split("");
33082                    if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && isFinite(opts.digits)) {
33083                        var radixPosition = $.inArray(opts.radixPoint, processValue);
33084                        var rpb = $.inArray(opts.radixPoint, maskedValue);
33085                        if (radixPosition === -1) {
33086                            processValue.push(opts.radixPoint);
33087                            radixPosition = processValue.length - 1;
33088                        }
33089                        for (var i = 1; i <= opts.digits; i++) {
33090                            if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && (processValue[radixPosition + i] === undefined || processValue[radixPosition + i] === opts.placeholder.charAt(0))) {
33091                                processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0);
33092                            } else if (rpb !== -1 && maskedValue[rpb + i] !== undefined) {
33093                                processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i];
33094                            }
33095                        }
33096                    }
33097                    if (opts.autoGroup === true && opts.groupSeparator !== "" && (charAtPos !== opts.radixPoint || currentResult.pos !== undefined || currentResult.dopost)) {
33098                        var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint;
33099                        processValue = Inputmask(buildPostMask(processValue, opts), {
33100                            numericInput: true,
33101                            jitMasking: true,
33102                            definitions: {
33103                                "*": {
33104                                    validator: "[0-9?]",
33105                                    cardinality: 1
33106                                }
33107                            }
33108                        }).format(processValue.join(""));
33109                        if (addRadix) processValue += opts.radixPoint;
33110                        if (processValue.charAt(0) === opts.groupSeparator) {
33111                            processValue.substr(1);
33112                        }
33113                    } else processValue = processValue.join("");
33114                }
33115                if (opts.isNegative && currentResult.event === "blur") {
33116                    opts.isNegative = processValue !== "0";
33117                }
33118                processValue = prefix + processValue;
33119                processValue += suffix;
33120                if (opts.isNegative) {
33121                    processValue = opts.negationSymbol.front + processValue;
33122                    processValue += opts.negationSymbol.back;
33123                }
33124                processValue = processValue.split("");
33125                if (charAtPos !== undefined) {
33126                    if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) {
33127                        caretPos = $.inArray("?", processValue);
33128                        if (caretPos > -1) {
33129                            processValue[caretPos] = charAtPos;
33130                        } else caretPos = currentResult.caret || 0;
33131                    } else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) {
33132                        var newCaretPos = $.inArray(charAtPos, processValue);
33133                        if (newCaretPos !== -1) caretPos = newCaretPos;
33134                    }
33135                }
33136                if (opts.numericInput) {
33137                    caretPos = processValue.length - caretPos - 1;
33138                    processValue = processValue.reverse();
33139                }
33140                var rslt = {
33141                    caret: (charAtPos === undefined || currentResult.pos !== undefined) && caretPos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos,
33142                    buffer: processValue,
33143                    refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("")
33144                };
33145                return rslt.refreshFromBuffer ? rslt : currentResult;
33146            },
33147            onBeforeWrite: function(e, buffer, caretPos, opts) {
33148                function parseMinMaxOptions(opts) {
33149                    if (opts.parseMinMaxOptions === undefined) {
33150                        if (opts.min !== null) {
33151                            opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
33152                            if (opts.radixPoint === ",") opts.min = opts.min.replace(opts.radixPoint, ".");
33153                            opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN;
33154                            if (isNaN(opts.min)) opts.min = Number.MIN_VALUE;
33155                        }
33156                        if (opts.max !== null) {
33157                            opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
33158                            if (opts.radixPoint === ",") opts.max = opts.max.replace(opts.radixPoint, ".");
33159                            opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN;
33160                            if (isNaN(opts.max)) opts.max = Number.MAX_VALUE;
33161                        }
33162                        opts.parseMinMaxOptions = "done";
33163                    }
33164                }
33165                if (e) {
33166                    switch (e.type) {
33167                      case "keydown":
33168                        return opts.postValidation(buffer, caretPos, {
33169                            caret: caretPos,
33170                            dopost: true
33171                        }, opts);
33172
33173                      case "blur":
33174                      case "checkval":
33175                        var unmasked;
33176                        parseMinMaxOptions(opts);
33177                        if (opts.min !== null || opts.max !== null) {
33178                            unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, {
33179                                unmaskAsNumber: true
33180                            }));
33181                            if (opts.min !== null && unmasked < opts.min) {
33182                                opts.isNegative = opts.min < 0;
33183                                return opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), caretPos, {
33184                                    caret: caretPos,
33185                                    dopost: true,
33186                                    placeholder: "0"
33187                                }, opts);
33188                            } else if (opts.max !== null && unmasked > opts.max) {
33189                                opts.isNegative = opts.max < 0;
33190                                return opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), caretPos, {
33191                                    caret: caretPos,
33192                                    dopost: true,
33193                                    placeholder: "0"
33194                                }, opts);
33195                            }
33196                        }
33197                        return opts.postValidation(buffer, caretPos, {
33198                            caret: caretPos,
33199                            placeholder: "0",
33200                            event: "blur"
33201                        }, opts);
33202
33203                      case "_checkval":
33204                        return {
33205                            caret: caretPos
33206                        };
33207
33208                      default:
33209                        break;
33210                    }
33211                }
33212            },
33213            regex: {
33214                integerPart: function(opts, emptyCheck) {
33215                    return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
33216                },
33217                integerNPart: function(opts) {
33218                    return new RegExp("[\\d" + Inputmask.escapeRegex(opts.groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+");
33219                }
33220            },
33221            definitions: {
33222                "~": {
33223                    validator: function(chrs, maskset, pos, strict, opts, isSelection) {
33224                        var isValid, l;
33225                        if (chrs === "k" || chrs === "m") {
33226                            isValid = {
33227                                insert: [],
33228                                c: 0
33229                            };
33230                            for (var i = 0, l = chrs === "k" ? 2 : 5; i < l; i++) {
33231                                isValid.insert.push({
33232                                    pos: pos + i,
33233                                    c: 0
33234                                });
33235                            }
33236                            isValid.pos = pos + l;
33237                            return isValid;
33238                        }
33239                        isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs);
33240                        if (isValid === true) {
33241           
33241                 if (opts.numericInput !== true && maskset.validPositions[pos] !== undefined && maskset.validPositions[pos].match.def === "~" && !isSelection) {
33242                                var processValue = maskset.buffer.join("");
33243                                processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), "");
33244                                processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
33245                                var pvRadixSplit = processValue.split(opts.radixPoint);
33246                                if (pvRadixSplit.length > 1) {
33247                                    pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0));
33248                                }
33249                                if (pvRadixSplit[0] === "0") {
33250                                    pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0));
33251                                }
33252                                processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || "";
33253                                var bufferTemplate = maskset._buffer.join("");
33254                                if (processValue === opts.radixPoint) {
33255                                    processValue = bufferTemplate;
33256                                }
33257                                while (processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$") === null) {
33258                                    bufferTemplate = bufferTemplate.slice(1);
33259                                }
33260                                processValue = processValue.replace(bufferTemplate, "");
33261                                processValue = processValue.split("");
33262                                if (processValue[pos] === undefined) {
33263                                    isValid = {
33264                                        pos: pos,
33265                                        remove: pos
33266                                    };
33267                                } else {
33268                                    isValid = {
33269                                        pos: pos
33270                                    };
33271                                }
33272                            }
33273                        } else if (!strict && chrs === opts.radixPoint && maskset.validPositions[pos - 1] === undefined) {
33274                            isValid = {
33275                                insert: {
33276                                    pos: pos,
33277                                    c: 0
33278                                },
33279                                pos: pos + 1
33280                            };
33281                        }
33282                        return isValid;
33283                    },
33284                    cardinality: 1
33285                },
33286                "+": {
33287                    validator: function(chrs, maskset, pos, strict, opts) {
33288                        return opts.allowMinus && (chrs === "-" || chrs === opts.negationSymbol.front);
33289                    },
33290                    cardinality: 1,
33291                    placeholder: ""
33292                },
33293                "-": {
33294                    validator: function(chrs, maskset, pos, strict, opts) {
33295                        return opts.allowMinus && chrs === opts.negationSymbol.back;
33296                    },
33297                    cardinality: 1,
33298                    placeholder: ""
33299                },
33300                ":": {
33301                    validator: function(chrs, maskset, pos, strict, opts) {
33302                        var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]";
33303                        var isValid = new RegExp(radix).test(chrs);
33304                        if (isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint) {
33305                            isValid = {
33306                                caret: pos + 1
33307                            };
33308                        }
33309                        return isValid;
33310                    },
33311                    cardinality: 1,
33312                    placeholder: function(opts) {
33313                        return opts.radixPoint;
33314                    }
33315                }
33316            },
33317            onUnMask: function(maskedValue, unmaskedValue, opts) {
33318                if (unmaskedValue === "" && opts.nullable === true) {
33319                    return unmaskedValue;
33320                }
33321                var processValue = maskedValue.replace(opts.prefix, "");
33322                processValue = processValue.replace(opts.suffix, "");
33323                processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), "");
33324                if (opts.placeholder.charAt(0) !== "") {
33325                    processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0");
33326                }
33327                if (opts.unmaskAsNumber) {
33328                    if (opts.radixPoint !== "" && processValue.indexOf(opts.radixPoint) !== -1) processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), ".");
33329                    processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-");
33330                    processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
33331                    return Number(processValue);
33332                }
33333                return processValue;
33334            },
33335            isComplete: function(buffer, opts) {
33336                var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join("");
33337                maskedValue = maskedValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-");
33338                maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), "");
33339                maskedValue = maskedValue.replace(opts.prefix, "");
33340                maskedValue = maskedValue.replace(opts.suffix, "");
33341                maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator) + "([0-9]{3})", "g"), "$1");
33342                if (opts.radixPoint === ",") maskedValue = maskedValue.replace(Inputmask.escapeRegex(opts.radixPoint), ".");
33343                return isFinite(maskedValue);
33344            },
33345            onBeforeMask: function(initialValue, opts) {
33346                opts.isNegative = undefined;
33347                var radixPoint = opts.radixPoint || ",";
33348                if ((typeof initialValue == "number" || opts.inputType === "number") && radixPoint !== "") {
33349                    initialValue = initialValue.toString().replace(".", radixPoint);
33350                }
33351                var valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = valueParts.length > 1 ? valueParts[1].replace(/[^0-9]/g, "") : "";
33352                initialValue = integerPart + (decimalPart !== "" ? radixPoint + decimalPart : decimalPart);
33353                var digits = 0;
33354                if (radixPoint !== "") {
33355                    digits = decimalPart.length;
33356                    if (decimalPart !== "") {
33357                        var digitsFactor = Math.pow(10, digits || 1);
33358                        if (isFinite(opts.digits)) {
33359                            digits = parseInt(opts.digits);
33360                            digitsFactor = Math.pow(10, digits);
33361                        }
33362                        initialValue = initialValue.replace(Inputmask.escapeRegex(radixPoint), ".");
33363                        if (isFinite(initialValue)) initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor;
33364                        initialValue = initialValue.toString().replace(".", radixPoint);
33365                    }
33366                }
33367                if (opts.digits === 0 && initialValue.indexOf(Inputmask.escapeRegex(radixPoint)) !== -1) {
33368                    initialValue = initialValue.substring(0, initialValue.indexOf(Inputmask.escapeRegex(radixPoint)));
33369                }
33370                return alignDigits(initialValue.toString().split(""), digits, opts).join("");
33371            },
33372            onKeyDown: function(e, buffer, caretPos, opts) {
33373                var $input = $(this);
33374                if (e.ctrlKey) {
33375                    switch (e.keyCode) {
33376                      case Inputmask.keyCode.UP:
33377                        $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step));
33378                        $input.trigger("setvalue");
33379                        break;
33380
33381                      case Inputmask.keyCode.DOWN:
33382                        $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step));
33383                        $input.trigger("setvalue");
33384                        break;
33385                    }
33386                }
33387            }
33388        },
33389        currency: {
33390            prefix: "$ ",
33391            groupSeparator: ",",
33392            alias: "numeric",
33393            placeholder: "0",
33394            autoGroup: true,
33395            digits: 2,
33396            digitsOptional: false,
33397            clearMaskOnLostFocus: false
33398        },
vendor: 9,815 bytes, lines 33399-33733
33399        decimal: {
33400            alias: "numeric"
33401        },
33402        integer: {
33403            alias: "numeric",
33404            digits: 0,
33405            radixPoint: ""
33406        },
33407        percentage: {
33408            alias: "numeric",
33409            digits: 2,
33410            digitsOptional: true,
33411            radixPoint: ".",
33412            placeholder: "0",
33413            autoGroup: false,
33414            min: 0,
33415            max: 100,
33416            suffix: " %",
33417            allowMinus: false
33418        }
33419    });
33420    return Inputmask;
33421});
33422/*! nouislider - 12.1.0 - 10/25/2018 */
33423(function(factory) {
33424    if (typeof define === "function" && define.amd) {
33425        // AMD. Register as an anonymous module.
33426        define([], factory);
33427    } else if (typeof exports === "object") {
33428        // Node/CommonJS
33429        module.exports = factory();
33430    } else {
33431        // Browser globals
33432        window.noUiSlider = factory();
33433    }
33434})(function() {
33435    "use strict";
33436
33437    var VERSION = "12.1.0";
33438
33439    function isValidFormatter(entry) {
33440        return typeof entry === "object" && typeof entry.to === "function" && typeof entry.from === "function";
33441    }
33442
33443    function removeElement(el) {
33444        el.parentElement.removeChild(el);
33445    }
33446
33447    function isSet(value) {
33448        return value !== null && value !== undefined;
33449    }
33450
33451    // Bindable version
33452    function preventDefault(e) {
33453        e.preventDefault();
33454    }
33455
33456    // Removes duplicates from an array.
33457    function unique(array) {
33458        return array.filter(function(a) {
33459            return !this[a] ? (this[a] = true) : false;
33460        }, {});
33461    }
33462
33463    // Round a value to the closest 'to'.
33464    function closest(value, to) {
33465        return Math.round(value / to) * to;
33466    }
33467
33468    // Current position of an element relative to the document.
33469    function offset(elem, orientation) {
33470        var rect = elem.getBoundingClientRect();
33471        var doc = elem.ownerDocument;
33472        var docElem = doc.documentElement;
33473        var pageOffset = getPageOffset(doc);
33474
33475        // getBoundingClientRect contains left scroll in Chrome on Android.
33476        // I haven't found a feature detection that proves this. Worst case
33477        // scenario on mis-match: the 'tap' feature on horizontal sliders breaks.
33478        if (/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)) {
33479            pageOffset.x = 0;
33480        }
33481
33482        return orientation
33483            ? rect.top + pageOffset.y - docElem.clientTop
33484            : rect.left + pageOffset.x - docElem.clientLeft;
33485    }
33486
33487    // Checks whether a value is numerical.
33488    function isNumeric(a) {
33489        return typeof a === "number" && !isNaN(a) && isFinite(a);
33490    }
33491
33492    // Sets a class and removes it after [duration] ms.
33493    function addClassFor(element, className, duration) {
33494        if (duration > 0) {
33495            addClass(element, className);
33496            setTimeout(function() {
33497                removeClass(element, className);
33498            }, duration);
33499        }
33500    }
33501
33502    // Limits a value to 0 - 100
33503    function limit(a) {
33504        return Math.max(Math.min(a, 100), 0);
33505    }
33506
33507    // Wraps a variable as an array, if it isn't one yet.
33508    // Note that an input array is returned by reference!
33509    function asArray(a) {
33510        return Array.isArray(a) ? a : [a];
33511    }
33512
33513    // Counts decimals
33514    function countDecimals(numStr) {
33515        numStr = String(numStr);
33516        var pieces = numStr.split(".");
33517        return pieces.length > 1 ? pieces[1].length : 0;
33518    }
33519
33520    // http://youmightnotneedjquery.com/#add_class
33521    function addClass(el, className) {
33522        if (el.classList) {
33523            el.classList.add(className);
33524        } else {
33525            el.className += " " + className;
33526        }
33527    }
33528
33529    // http://youmightnotneedjquery.com/#remove_class
33530    function removeClass(el, className) {
33531        if (el.classList) {
33532            el.classList.remove(className);
33533        } else {
33534            el.className = el.className.replace(
33535                new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"),
33536                " "
33537            );
33538        }
33539    }
33540
33541    // https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/
33542    function hasClass(el, className) {
33543        return el.classList
33544            ? el.classList.contains(className)
33545            : new RegExp("\\b" + className + "\\b").test(el.className);
33546    }
33547
33548    // https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
33549    function getPageOffset(doc) {
33550        var supportPageOffset = window.pageXOffset !== undefined;
33551        var isCSS1Compat = (doc.compatMode || "") === "CSS1Compat";
33552        var x = supportPageOffset
33553            ? window.pageXOffset
33554            : isCSS1Compat
33555                ? doc.documentElement.scrollLeft
33556                : doc.body.scrollLeft;
33557        var y = supportPageOffset
33558            ? window.pageYOffset
33559            : isCSS1Compat
33560                ? doc.documentElement.scrollTop
33561                : doc.body.scrollTop;
33562
33563        return {
33564            x: x,
33565            y: y
33566        };
33567    }
33568
33569    // we provide a function to compute constants instead
33570    // of accessing window.* as soon as the module needs it
33571    // so that we do not compute anything if not needed
33572    function getActions() {
33573        // Determine the events to bind. IE11 implements pointerEvents without
33574        // a prefix, which breaks compatibility with the IE10 implementation.
33575        return window.navigator.pointerEnabled
33576            ? {
33577                  start: "pointerdown",
33578                  move: "pointermove",
33579                  end: "pointerup"
33580              }
33581            : window.navigator.msPointerEnabled
33582                ? {
33583                      start: "MSPointerDown",
33584                      move: "MSPointerMove",
33585                      end: "MSPointerUp"
33586                  }
33587                : {
33588                      start: "mousedown touchstart",
33589                      move: "mousemove touchmove",
33590                      end: "mouseup touchend"
33591                  };
33592    }
33593
33594    // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
33595    // Issue #785
33596    function getSupportsPassive() {
33597        var supportsPassive = false;
33598
33599        /* eslint-disable */
33600        try {
33601            var opts = Object.defineProperty({}, "passive", {
33602                get: function() {
33603                    supportsPassive = true;
33604                }
33605            });
33606
33607            window.addEventListener("test", null, opts);
33608        } catch (e) {}
33609        /* eslint-enable */
33610
33611        return supportsPassive;
33612    }
33613
33614    function getSupportsTouchActionNone() {
33615        return window.CSS && CSS.supports && CSS.supports("touch-action", "none");
33616    }
33617
33618    // Value calculation
33619
33620    // Determine the size of a sub-range in relation to a full range.
33621    function subRangeRatio(pa, pb) {
33622        return 100 / (pb - pa);
33623    }
33624
33625    // (percentage) How many percent is this value of this range?
33626    function fromPercentage(range, value) {
33627        return (value * 100) / (range[1] - range[0]);
33628    }
33629
33630    // (percentage) Where is this value on this range?
33631    function toPercentage(range, value) {
33632        return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0]);
33633    }
33634
33635    // (value) How much is this percentage on this range?
33636    function isPercentage(range, value) {
33637        return (value * (range[1] - range[0])) / 100 + range[0];
33638    }
33639
33640    // Range conversion
33641
33642    function getJ(value, arr) {
33643        var j = 1;
33644
33645        while (value >= arr[j]) {
33646            j += 1;
33647        }
33648
33649        return j;
33650    }
33651
33652    // (percentage) Input a value, find where, on a scale of 0-100, it applies.
33653    function toStepping(xVal, xPct, value) {
33654        if (value >= xVal.slice(-1)[0]) {
33655            return 100;
33656        }
33657
33658        var j = getJ(value, xVal);
33659        var va = xVal[j - 1];
33660        var vb = xVal[j];
33661        var pa = xPct[j - 1];
33662        var pb = xPct[j];
33663
33664        return pa + toPercentage([va, vb], value) / subRangeRatio(pa, pb);
33665    }
33666
33667    // (value) Input a percentage, find where it is on the specified range.
33668    function fromStepping(xVal, xPct, value) {
33669        // There is no range group that fits 100
33670        if (value >= 100) {
33671            return xVal.slice(-1)[0];
33672        }
33673
33674        var j = getJ(value, xPct);
33675        var va = xVal[j - 1];
33676        var vb = xVal[j];
33677        var pa = xPct[j - 1];
33678        var pb = xPct[j];
33679
33680        return isPercentage([va, vb], (value - pa) * subRangeRatio(pa, pb));
33681    }
33682
33683    // (percentage) Get the step that applies at a certain value.
33684    function getStep(xPct, xSteps, snap, value) {
33685        if (value === 100) {
33686            return value;
33687        }
33688
33689        var j = getJ(value, xPct);
33690        var a = xPct[j - 1];
33691        var b = xPct[j];
33692
33693        // If 'snap' is set, steps are used as fixed points on the slider.
33694        if (snap) {
33695            // Find the closest position, a or b.
33696            if (value - a > (b - a) / 2) {
33697                return b;
33698            }
33699
33700            return a;
33701        }
33702
33703        if (!xSteps[j - 1]) {
33704            return value;
33705        }
33706
33707        return xPct[j - 1] + closest(value - xPct[j - 1], xSteps[j - 1]);
33708    }
33709
33710    // Entry parsing
33711
33712    function handleEntryPoint(index, value, that) {
33713        var percentage;
33714
33715        // Wrap numerical input in an array.
33716        if (typeof value === "number") {
33717            value = [value];
33718        }
33719
33720        // Reject any invalid input, by testing whether value is an array.
33721        if (!Array.isArray(value)) {
33722            throw new Error("noUiSlider (" + VERSION + "): 'range' contains invalid value.");
33723        }
33724
33725        // Covert min/max syntax to 0 and 100.
33726        if (index === "min") {
33727            percentage = 0;
33728        } else if (index === "max") {
33729            percentage = 100;
33730        } else {
33731            percentage = parseFloat(index);
33732        }
33733
33734        // Check for correct input.
33735        if (!isNumeric(percentage) || !isNumeric(value[0])) {
33736            throw new Error("noUiSlider (" + VERSION + "): 'range' value isn't numeric.");
33737        }
33738
33739        // Store values.
33740        that.xPct.push(percentage);
33741        that.xVal.push(value[0]);
33742
33743        // NaN will evaluate to false too, but to keep
33744        // logging clear, set step explicitly. Make sure
33745        // not to override the 'step' setting with false.
33746        if (!percentage) {
33747            if (!isNaN(value[1])) {
33748                that.xSteps[0] = value[1];
33749            }
33750        } else {
33751            that.xSteps.push(isNaN(value[1]) ? false : value[1]);
33752        }
33753
33754        that.xHighestCompleteStep.push(0);
33755    }
33756
33757    function handleStepPoint(i, n, that) {
33758        // Ignore 'false' stepping.
33759        if (!n) {
33760            return true;
33761        }
33762
33763        // Factor to range ratio
33764        that.xSteps[i] =
33765            fromPercentage([that.xVal[i], that.xVal[i + 1]], n) / subRangeRatio(that.xPct[i], that.xPct[i + 1]);
33766
33767        var totalSteps = (that.xVal[i + 1] - that.xVal[i]) / that.xNumSteps[i];
33768        var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
33769        var step = that.xVal[i] + that.xNumSteps[i] * highestStep;
33770
33771        that.xHighestCompleteStep[i] = step;
33772    }
33773
33774    // Interface
33775
33776    function Spectrum(entry, snap, singleStep) {
33777        this.xPct = [];
33778        this.xVal = [];
33779        this.xSteps = [singleStep || false];
33780        this.xNumSteps = [false];
33781        this.xHighestCompleteStep = [];
33782
33783        this.snap = snap;
33784
33785        var index;
33786        var ordered = []; // [0, 'min'], [1, '50%'], [2, 'max']
33787
33788        // Map the object keys to an array.
33789        for (index in entry) {
33790            if (entry.hasOwnProperty(index)) {
33791                ordered.push([entry[index], index]);
33792            }
33793        }
33794
33795        // Sort all entries by value (numeric sort).
33796        if (ordered.length && typeof ordered[0][0] === "object") {
33797            ordered.sort(function(a, b) {
33798                return a[0][0] - b[0][0];
33799            });
33800        } else {
33801            ordered.sort(function(a, b) {
33802                return a[0] - b[0];
33803            });
33804        }
33805
33806        // Convert all entries to subranges.
33807        for (index = 0; index < ordered.length; index++) {
33808            handleEntryPoint(ordered[index][1], ordered[index][0], this);
33809        }
33810
33811        // Store the actual step values.
33812        // xSteps is sorted in the same order as xPct and xVal.
33813        this.xNumSteps = this.xSteps.slice(0);
33814
33815        // Convert all numeric steps to the percentage of the subrange they represent.
33816        for (index = 0; index < this.xNumSteps.length; index++) {
33817            handleStepPoint(index, this.xNumSteps[index], this);
33818        }
33819    }
33820
33821    Spectrum.prototype.getMargin = function(value) {
33822        var step = this.xNumSteps[0];
33823
33824        if (step && (value / step) % 1 !== 0) {
33825            throw new Error("noUiSlider (" + VERSION + "): 'limit', 'margin' and 'padding' must be divisible by step.");
33826        }
33827
33828        return this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false;
33829    };
33830
33831    Spectrum.prototype.toStepping = function(value) {
33832        value = toStepping(this.xVal, this.xPct, value);
33833
33834        return value;
33835    };
33836
33837    Spectrum.prototype.fromStepping = function(value) {
33838        return fromStepping(this.xVal, this.xPct, value);
33839    };
33840
33841    Spectrum.prototype.getStep = function(value) {
33842        value = getStep(this.xPct, this.xSteps, this.snap, value);
33843
33844        return value;
33845    };
33846
33847    Spectrum.prototype.getNearbySteps = function(value) {
33848        var j = getJ(value, this.xPct);
33849
33850        return {
33851            stepBefore: {
33852                startValue: this.xVal[j - 2],
33853                step: this.xNumSteps[j - 2],
33854                highestStep: this.xHighestCompleteStep[j - 2]
33855            },
33856            thisStep: {
33857                startValue: this.xVal[j - 1],
33858                step: this.xNumSteps[j - 1],
33859                highestStep: this.xHighestCompleteStep[j - 1]
33860            },
33861            stepAfter: {
33862                startValue: this.xVal[j],
33863                step: this.xNumSteps[j],
33864                highestStep: this.xHighestCompleteStep[j]
33865            }
33866        };
33867    };
33868
33869    Spectrum.prototype.countStepDecimals = function() {
33870        var stepDecimals = this.xNumSteps.map(countDecimals);
33871        return Math.max.apply(null, stepDecimals);
33872    };
33873
33874    // Outside testing
33875    Spectrum.prototype.convert = function(value) {
33876        return this.getStep(this.toStepping(value));
33877    };
33878
33879    /*	Every input option is tested and parsed. This'll prevent
33880        endless validation in internal methods. These tests are
33881        structured with an item for every option available. An
33882        option can be marked as required by setting the 'r' flag.
33883        The testing function is provided with three arguments:
33884            - The provided value for the option;
33885            - A reference to the options object;
33886            - The name for the option;
33887
33888        The testing function returns false when an error is detected,
33889        or true when everything is OK. It can also modify the option
33890        object, to make sure all values can be correctly looped elsewhere. */
33891
33892    var defaultFormatter = {
33893        to: function(value) {
33894            return value !== undefined && value.toFixed(2);
33895        },
33896        from: Number
33897    };
33898
33899    function validateFormat(entry) {
33900        // Any object with a to and from method is supported.
33901        if (isValidFormatter(entry)) {
33902            return true;
33903        }
33904
33905        throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods.");
33906    }
33907
33908    function testStep(parsed, entry) {
33909        if (!isNumeric(entry)) {
33910            throw new Error("noUiSlider (" + VERSION + "): 'step' is not numeric.");
33911        }
33912
33913        // The step option can still be used to set stepping
33914        // for linear sliders. Overwritten if set in 'range'.
33915        parsed.singleStep = entry;
33916    }
33917
33918    function testRange(parsed, entry) {
33919        // Filter incorrect input.
33920        if (typeof entry !== "object" || Array.isArray(entry)) {
33921            throw new Error("noUiSlider (" + VERSION + "): 'range' is not an object.");
33922        }
33923
33924        // Catch missing start or end.
33925        if (entry.min === undefined || entry.max === undefined) {
33926            throw new Error("noUiSlider (" + VERSION + "): Missing 'min' or 'max' in 'range'.");
33927        }
33928
33929        // Catch equal start or end.
33930        if (entry.min === entry.max) {
33931            throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal.");
33932        }
33933
33934        parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep);
33935    }
33936
33937    function testStart(parsed, entry) {
33938        entry = asArray(entry);
33939
33940        // Validate input. Values aren't tested, as the public .val method
33941        // will always provide a valid location.
33942        if (!Array.isArray(entry) || !entry.length) {
33943            throw new Error("noUiSlider (" + VERSION + "): 'start' option is incorrect.");
33944        }
33945
33946        // Store the number of handles.
33947        parsed.handles = entry.length;
33948
33949        // When the slider is initialized, the .val method will
33950        // be called with the start options.
33951        parsed.start = entry;
33952    }
33953
33954    function testSnap(parsed, entry) {
33955        // Enforce 100% stepping within subranges.
33956        parsed.snap = entry;
33957
33958        if (typeof entry !== "boolean") {
33959            throw new Error("noUiSlider (" + VERSION + "): 'snap' option must be a boolean.");
33960        }
33961    }
33962
33963    function testAnimate(parsed, entry) {
33964        // Enforce 100% stepping within subranges.
33965        parsed.animate = entry;
33966
33967        if (typeof entry !== "boolean") {
33968            throw new Error("noUiSlider (" + VERSION + "): 'animate' option must be a boolean.");
33969        }
33970    }
33971
33972    function testAnimationDuration(parsed, entry) {
33973        parsed.animationDuration = entry;
33974
33975        if (typeof entry !== "number") {
33976            throw new Error("noUiSlider (" + VERSION + "): 'animationDuration' option must be a number.");
33977        }
33978    }
33979
33980    function testConnect(parsed, entry) {
33981        var connect = [false];
33982        var i;
33983
33984        // Map legacy options
33985        if (entry === "lower") {
33986            entry = [true, false];
33987        } else if (entry === "upper") {
33988            entry = [false, true];
33989        }
33990
33991        // Handle boolean options
33992        if (entry === true || entry === false) {
33993            for (i = 1; i < parsed.handles; i++) {
33994                connect.push(entry);
33995            }
33996
33997            connect.push(false);
33998        }
33999
34000        // Reject invalid input
34001        else if (!Array.isArray(entry) || !entry.length || entry.length !== parsed.handles + 1) {
34002            throw new Error("noUiSlider (" + VERSION + "): 'connect' option doesn't match handle count.");
34003        } else {
34004            connect = entry;
34005        }
34006
34007        parsed.connect = connect;
34008    }
34009
34010    function testOrientation(parsed, entry) {
34011        // Set orientation to an a numerical value for easy
34012        // array selection.
34013        switch (entry) {
34014            case "horizontal":
34015                parsed.ort = 0;
34016                break;
34017            case "vertical":
34018                parsed.ort = 1;
34019                break;
34020            default:
34021                throw new Error("noUiSlider (" + VERSION + "): 'orientation' option is invalid.");
34022        }
34023    }
34024
34025    function testMargin(parsed, entry) {
34026        if (!isNumeric(entry)) {
34027            throw new Error("noUiSlider (" + VERSION + "): 'margin' option must be numeric.");
34028        }
34029
34030        // Issue #582
34031        if (entry === 0) {
34032            return;
34033        }
34034
34035        parsed.margin = parsed.spectrum.getMargin(entry);
34036
34037        if (!parsed.margin) {
34038            throw new Error("noUiSlider (" + VERSION + "): 'margin' option is only supported on linear sliders.");
34039        }
34040    }
34041
34042    function testLimit(parsed, entry) {
34043        if (!isNumeric(entry)) {
34044            throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric.");
34045        }
34046
34047        parsed.limit = parsed.spectrum.getMargin(entry);
34048
34049        if (!parsed.limit || parsed.handles < 2) {
34050            throw new Error(
34051                "noUiSlider (" +
34052                    VERSION +
34053                    "): 'limit' option is only supported on linear sliders with 2 or more handles."
34054            );
34055        }
34056    }
34057
34058    function testPadding(parsed, entry) {
34059        if (!isNumeric(entry) && !Array.isArray(entry)) {
34060            throw new Error(
34061                "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
34062            );
34063        }
34064
34065        if (Array.isArray(entry) && !(entry.length === 2 || isNumeric(entry[0]) || isNumeric(entry[1]))) {
34066            throw new Error(
34067                "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
34068            );
34069        }
34070
34071        if (entry === 0) {
34072            return;
34073        }
34074
34075        if (!Array.isArray(entry)) {
34076            entry = [entry, entry];
34077        }
34078
34079        // 'getMargin' returns false for invalid values.
34080        parsed.padding = [parsed.spectrum.getMargin(entry[0]), parsed.spectrum.getMargin(entry[1])];
34081
34082        if (parsed.padding[0] === false || parsed.padding[1] === false) {
34083            throw new Error("noUiSlider (" + VERSION + "): 'padding' option is only supported on linear sliders.");
34084        }
34085
34086        if (parsed.padding[0] < 0 || parsed.padding[1] < 0) {
34087            throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number(s).");
34088        }
34089
34090        if (parsed.padding[0] + parsed.padding[1] >= 100) {
34091            throw new Error("noUiSlider (" + VERSION + "): 'padding' option must not exceed 100% of the range.");
34092        }
34093    }
34094
34095    function testDirection(parsed, entry) {
34096        // Set direction as a numerical value for easy parsing.
34097        // Invert connection for RTL sliders, so that the proper
34098        // handles get the connect/background classes.
34099        switch (entry) {
34100            case "ltr":
34101                parsed.dir = 0;
34102                break;
34103            case "rtl":
34104                parsed.dir = 1;
34105                break;
34106            default:
34107                throw new Error("noUiSlider (" + VERSION + "): 'direction' option was not recognized.");
34108        }
34109    }
34110
34111    function testBehaviour(parsed, entry) {
34112        // Make sure the input is a string.
34113        if (typeof entry !== "string") {
34114            throw new Error("noUiSlider (" + VERSION + "): 'behaviour' must be a string containing options.");
34115        }
34116
34117        // Check if the string contains any keywords.
34118        // None are required.
34119        var tap = entry.indexOf("tap") >= 0;
34120        var drag = entry.indexOf("drag") >= 0;
34121        var fixed = entry.indexOf("fixed") >= 0;
34122        var snap = entry.indexOf("snap") >= 0;
34123        var hover = entry.indexOf("hover") >= 0;
34124        var unconstrained = entry.indexOf("unconstrained") >= 0;
34125
34126        if (fixed) {
34127            if (parsed.handles !== 2) {
34128                throw new Error("noUiSlider (" + VERSION + "): 'fixed' behaviour must be used with 2 handles");
34129            }
34130
34131            // Use margin to enforce fixed state
34132            testMargin(parsed, parsed.start[1] - parsed.start[0]);
34133        }
34134
34135        if (unconstrained && (parsed.margin || parsed.limit)) {
34136            throw new Error(
34137                "noUiSlider (" + VERSION + "): 'unconstrained' behaviour cannot be used with margin or limit"
34138            );
34139        }
34140
34141        parsed.events = {
34142            tap: tap || snap,
34143            drag: drag,
34144            fixed: fixed,
34145            snap: snap,
34146            hover: hover,
34147            unconstrained: unconstrained
34148        };
34149    }
34150
34151    function testTooltips(parsed, entry) {
34152        if (entry === false) {
34153            return;
34154        }
34155
34156        if (entry === true) {
34157            parsed.tooltips = [];
34158
34159            for (var i = 0; i < parsed.handles; i++) {
34160                parsed.tooltips.push(true);
34161            }
34162        } else {
34163            parsed.tooltips = asArray(entry);
34164
34165            if (parsed.tooltips.length !== parsed.handles) {
34166                throw new Error("noUiSlider (" + VERSION + "): must pass a formatter for all handles.");
34167            }
34168
34169            parsed.tooltips.forEach(function(formatter) {
34170                if (
34171                    typeof formatter !== "boolean" &&
34172                    (typeof formatter !== "object" || typeof formatter.to !== "function")
34173                ) {
34174                    throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'.");
34175                }
34176            });
34177        }
34178    }
34179
34180    function testAriaFormat(parsed, entry) {
34181        parsed.ariaFormat = entry;
34182        validateFormat(entry);
34183    }
34184
34185    function testFormat(parsed, entry) {
34186        parsed.format = entry;
34187        validateFormat(entry);
34188    }
34189
34190    function testKeyboardSupport(parsed, entry) {
34191        parsed.keyboardSupport = entry;
34192
34193        if (typeof entry !== "boolean") {
34194            throw new Error("noUiSlider (" + VERSION + "): 'keyboardSupport' option must be a boolean.");
34195        }
34196    }
34197
34198    function testDocumentElement(parsed, entry) {
34199        // This is an advanced option. Passed values are used without validation.
34200        parsed.documentElement = entry;
34201    }
34202
34203    function testCssPrefix(parsed, entry) {
34204        if (typeof entry !== "string" && entry !== false) {
34205            throw new Error("noUiSlider (" + VERSION + "): 'cssPrefix' must be a string or `false`.");
34206        }
34207
34208        parsed.cssPrefix = entry;
34209    }
34210
34211    function testCssClasses(parsed, entry) {
34212        if (typeof entry !== "object") {
34213            throw new Error("noUiSlider (" + VERSION + "): 'cssClasses' must be an object.");
34214        }
34215
34216        if (typeof parsed.cssPrefix === "string") {
34217            parsed.cssClasses = {};
34218
34219            for (var key in entry) {
34220                if (!entry.hasOwnProperty(key)) {
34221                    continue;
34222                }
34223
34224                parsed.cssClasses[key] = parsed.cssPrefix + entry[key];
34225            }
34226        } else {
34227            parsed.cssClasses = entry;
34228        }
34229    }
34230
34231    // Test all developer settings and parse to assumption-safe values.
34232    function testOptions(options) {
34233        // To prove a fix for #537, freeze options here.
34234        // If the object is modified, an error will be thrown.
34235        // Object.freeze(options);
34236
34237        var parsed = {
34238            margin: 0,
34239            limit: 0,
34240            padding: 0,
34241            animate: true,
34242            animationDuration: 300,
34243            ariaFormat: defaultFormatter,
34244            format: defaultFormatter
34245        };
34246
34247        // Tests are executed in the order they are presented here.
34248        var tests = {
34249            step: { r: false, t: testStep },
34250            start: { r: true, t: testStart },
34251            connect: { r: true, t: testConnect },
34252            direction: { r: true, t: testDirection },
34253            snap: { r: false, t: testSnap },
34254            animate: { r: false, t: testAnimate },
34255            animationDuration: { r: false, t: testAnimationDuration },
34256            range: { r: true, t: testRange },
34257            orientation: { r: false, t: testOrientation },
34258            margin: { r: false, t: testMargin },
34259            limit: { r: false, t: testLimit },
34260            padding: { r: false, t: testPadding },
34261            behaviour: { r: true, t: testBehaviour },
34262            ariaFormat: { r: false, t: testAriaFormat },
34263            format: { r: false, t: testFormat },
34264            tooltips: { r: false, t: testTooltips },
34265            keyboardSupport: { r: true, t: testKeyboardSupport },
34266            documentElement: { r: false, t: testDocumentElement },
34267            cssPrefix: { r: true, t: testCssPrefix },
34268            cssClasses: { r: true, t: testCssClasses }
34269        };
34270
34271        var defaults = {
34272            connect: false,
34273            direction: "ltr",
34274            behaviour: "tap",
34275            orientation: "horizontal",
34276            keyboardSupport: true,
34277            cssPrefix: "noUi-",
34278            cssClasses: {
34279                target: "target",
34280                base: "base",
34281                origin: "origin",
34282                handle: "handle",
34283                handleLower: "handle-lower",
34284                handleUpper: "handle-upper",
34285                horizontal: "horizontal",
34286                vertical: "vertical",
34287                background: "background",
34288                connect: "connect",
34289                connects: "connects",
34290                ltr: "ltr",
34291                rtl: "rtl",
34292                draggable: "draggable",
34293                drag: "state-drag",
34294                tap: "state-tap",
34295                active: "active",
34296                tooltip: "tooltip",
34297                pips: "pips",
34298                pipsHorizontal: "pips-horizontal",
34299                pipsVertical: "pips-vertical",
34300                marker: "marker",
34301                markerHorizontal: "marker-horizontal",
34302                markerVertical: "marker-vertical",
34303                markerNormal: "marker-normal",
34304                markerLarge: "marker-large",
34305                markerSub: "marker-sub",
34306                value: "value",
34307                valueHorizontal: "value-horizontal",
34308                valueVertical: "value-vertical",
34309                valueNormal: "value-normal",
34310                valueLarge: "value-large",
34311                valueSub: "value-sub"
34312            }
34313        };
34314
34315        // AriaFormat defaults to regular format, if any.
34316        if (options.format && !options.ariaFormat) {
34317            options.ariaFormat = options.format;
34318        }
34319
34320        // Run all options through a testing mechanism to ensure correct
34321        // input. It should be noted that options might get modified to
34322        // be handled properly. E.g. wrapping integers in arrays.
34323        Object.keys(tests).forEach(function(name) {
34324            // If the option isn't set, but it is required, throw an error.
34325            if (!isSet(options[name]) && defaults[name] === undefined) {
34326                if (tests[name].r) {
34327                    throw new Error("noUiSlider (" + VERSION + "): '" + name + "' is required.");
34328                }
34329
34330                return true;
34331            }
34332
34333            tests[name].t(parsed, !isSet(options[name]) ? defaults[name] : options[name]);
34334        });
34335
34336        // Forward pips options
34337        parsed.pips = options.pips;
34338
34339        // All recent browsers accept unprefixed transform.
34340        // We need -ms- for IE9 and -webkit- for older Android;
34341        // Assume use of -webkit- if unprefixed and -ms- are not supported.
34342        // https://caniuse.com/#feat=transforms2d
34343        var d = document.createElement("div");
34344        var msPrefix = d.style.msTransform !== undefined;
34345        var noPrefix = d.style.transform !== undefined;
34346
34347        parsed.transformRule = noPrefix ? "transform" : msPrefix ? "msTransform" : "webkitTransform";
34348
34349        // Pips don't move, so we can place them using left/top.
34350        var styles = [["left", "top"], ["right", "bottom"]];
34351
34352        parsed.style = styles[parsed.dir][parsed.ort];
34353
34354        return parsed;
34355    }
34356
34357    function scope(target, options, originalOptions) {
34358        var actions = getActions();
34359        var supportsTouchActionNone = getSupportsTouchActionNone();
34360        var supportsPassive = supportsTouchActionNone && getSupportsPassive();
34361
34362        // All variables local to 'scope' are prefixed with 'scope_'
34363        var scope_Target = target;
34364        var scope_Locations = [];
34365        var scope_Base;
34366        var scope_Handles;
34367        var scope_HandleNumbers = [];
34368        var scope_ActiveHandlesCount = 0;
34369        var scope_Connects;
34370        var scope_Spectrum = options.spectrum;
34371        var scope_Values = [];
34372        var scope_Events = {};
34373        var scope_Self;
34374        var scope_Pips;
34375        var scope_Document = target.ownerDocument;
34376        var scope_DocumentElement = options.documentElement || scope_Document.documentElement;
34377        var scope_Body = scope_Document.body;
34378
34379        // Pips constants
34380        var PIPS_NONE = -1;
34381        var PIPS_NO_VALUE = 0;
34382        var PIPS_LARGE_VALUE = 1;
34383        var PIPS_SMALL_VALUE = 2;
34384
34385        // For horizontal sliders in standard ltr documents,
34386        // make .noUi-origin overflow to the left so the document doesn't scroll.
34387        var scope_DirOffset = scope_Document.dir === "rtl" || options.ort === 1 ? 0 : 100;
34388
34389        // Creates a node, adds it to target, returns the new node.
34390        function addNodeTo(addTarget, className) {
34391            var div = scope_Document.createElement("div");
34392
34393            if (className) {
34394                addClass(div, className);
34395            }
34396
34397            addTarget.appendChild(div);
34398
34399            return div;
34400        }
34401
34402        // Append a origin to the base
34403        function addOrigin(base, handleNumber) {
34404            var origin = addNodeTo(base, options.cssClasses.origin);
34405            var handle = addNodeTo(origin, options.cssClasses.handle);
34406
34407            handle.setAttribute("data-handle", handleNumber);
34408
34409            if (options.keyboardSupport) {
34410                // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
34411                // 0 = focusable and reachable
34412                handle.setAttribute("tabindex", "0");
34413            }
34414
34415            handle.setAttribute("role", "slider");
34416            handle.setAttribute("aria-orientation", options.ort ? "vertical" : "horizontal");
34417
34418            if (handleNumber === 0) {
34419                addClass(handle, options.cssClasses.handleLower);
34420            } else if (handleNumber === options.handles - 1) {
34421                addClass(handle, options.cssClasses.handleUpper);
34422            }
34423
34424            return origin;
34425        }
34426
34427        // Insert nodes for connect elements
34428        function addConnect(base, add) {
34429            if (!add) {
34430                return false;
34431            }
34432
34433            return addNodeTo(base, options.cssClasses.connect);
34434        }
34435
34436        // Add handles to the slider base.
34437        function addElements(connectOptions, base) {
34438            var connectBase = addNodeTo(base, options.cssClasses.connects);
34439
34440            scope_Handles = [];
34441            scope_Connects = [];
34442
34443            scope_Connects.push(addConnect(connectBase, connectOptions[0]));
34444
34445            // [::::O====O====O====]
34446            // connectOptions = [0, 1, 1, 1]
34447
34448            for (var i = 0; i < options.handles; i++) {
34449                // Keep a list of all added handles.
34450                scope_Handles.push(addOrigin(base, i));
34451                scope_HandleNumbers[i] = i;
34452                scope_Connects.push(addConnect(connectBase, connectOptions[i + 1]));
34453            }
34454        }
34455
34456        // Initialize a single slider.
34457        function addSlider(addTarget) {
34458            // Apply classes and data to the target.
34459            addClass(addTarget, options.cssClasses.target);
34460
34461            if (options.dir === 0) {
34462                addClass(addTarget, options.cssClasses.ltr);
34463            } else {
34464                addClass(addTarget, options.cssClasses.rtl);
34465            }
34466
34467            if (options.ort === 0) {
34468                addClass(addTarget, options.cssClasses.horizontal);
34469            } else {
34470                addClass(addTarget, options.cssClasses.vertical);
34471            }
34472
34473            return addNodeTo(addTarget, options.cssClasses.base);
34474        }
34475
34476        function addTooltip(handle, handleNumber) {
34477            if (!options.tooltips[handleNumber]) {
34478                return false;
34479            }
34480
34481            return addNodeTo(handle.firstChild, options.cssClasses.tooltip);
34482        }
34483
34484        // The tooltips option is a shorthand for using the 'update' event.
34485        function tooltips() {
34486            // Tooltips are added with options.tooltips in original order.
34487            var tips = scope_Handles.map(addTooltip);
34488
34489            bindEvent("update", function(values, handleNumber, unencoded) {
34490                if (!tips[handleNumber]) {
34491                    return;
34492                }
34493
34494                var formattedValue = values[handleNumber];
34495
34496                if (options.tooltips[handleNumber] !== true) {
34497                    formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]);
34498                }
34499
34500                tips[handleNumber].innerHTML = formattedValue;
34501            });
34502        }
34503
34504        function aria() {
34505            bindEvent("update", function(values, handleNumber, unencoded, tap, positions) {
34506                // Update Aria Values for all handles, as a change in one changes min and max values for the next.
34507                scope_HandleNumbers.forEach(function(index) {
34508                    var handle = scope_Handles[index];
34509
34510                    var min = checkHandlePosition(scope_Locations, index, 0, true, true, true);
34511                    var max = checkHandlePosition(scope_Locations, index, 100, true, true, true);
34512
34513                    var now = positions[index];
34514
34515                    // Formatted value for display
34516                    var text = options.ariaFormat.to(unencoded[index]);
34517
34518                    // Map to slider range values
34519                    min = scope_Spectrum.fromStepping(min).toFixed(1);
34520                    max = scope_Spectrum.fromStepping(max).toFixed(1);
34521                    now = scope_Spectrum.fromStepping(now).toFixed(1);
34522
34523                    handle.children[0].setAttribute("aria-valuemin", min);
34524                    handle.children[0].setAttribute("aria-valuemax", max);
34525                    handle.children[0].setAttribute("aria-valuenow", now);
34526                    handle.children[0].setAttribute("aria-valuetext", text);
34527                });
34528            });
34529        }
34530
34531        function getGroup(mode, values, stepped) {
34532            // Use the range.
34533            if (mode === "range" || mode === "steps") {
34534                return scope_Spectrum.xVal;
34535            }
34536
34537            if (mode === "count") {
34538                if (values < 2) {
34539                    throw new Error("noUiSlider (" + VERSION + "): 'values' (>= 2) required for mode 'count'.");
34540                }
34541
34542                // Divide 0 - 100 in 'count' parts.
34543                var interval = values - 1;
34544                var spread = 100 / interval;
34545
34546                values = [];
34547
34548                // List these parts and have them handled as 'positions'.
34549                while (interval--) {
34550                    values[interval] = interval * spread;
34551                }
34552
34553                values.push(100);
34554
34555                mode = "positions";
34556            }
34557
34558            if (mode === "positions") {
34559                // Map all percentages to on-range values.
34560                return values.map(function(value) {
34561                    return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value);
34562                });
34563            }
34564
34565            if (mode === "values") {
34566                // If the value must be stepped, it needs to be converted to a percentage first.
34567                if (stepped) {
34568                    return values.map(function(value) {
34569                        // Convert to percentage, apply step, return to value.
34570                        return scope_Spectrum.fromStepping(scope_Spectrum.getStep(scope_Spectrum.toStepping(value)));
34571                    });
34572                }
34573
34574                // Otherwise, we can simply use the values.
34575                return values;
34576            }
34577        }
34578
34579        function generateSpread(density, mode, group) {
34580            function safeIncrement(value, increment) {
34581                // Avoid floating point variance by dropping the smallest decimal places.
34582                return (value + increment).toFixed(7) / 1;
34583            }
34584
34585            var indexes = {};
34586            var firstInRange = scope_Spectrum.xVal[0];
34587            var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length - 1];
34588            var ignoreFirst = false;
vendor: 4,581 bytes, lines 34589-34698
34589            var ignoreLast = false;
34590            var prevPct = 0;
34591
34592            // Create a copy of the group, sort it and filter away all duplicates.
34593            group = unique(
34594                group.slice().sort(function(a, b) {
34595                    return a - b;
34596                })
34597            );
34598
34599            // Make sure the range starts with the first element.
34600            if (group[0] !== firstInRange) {
34601                group.unshift(firstInRange);
34602                ignoreFirst = true;
34603            }
34604
34605            // Likewise for the last one.
34606            if (group[group.length - 1] !== lastInRange) {
34607                group.push(lastInRange);
34608                ignoreLast = true;
34609            }
34610
34611            group.forEach(function(current, index) {
34612                // Get the current step and the lower + upper positions.
34613                var step;
34614                var i;
34615                var q;
34616                var low = current;
34617                var high = group[index + 1];
34618                var newPct;
34619                var pctDifference;
34620                var pctPos;
34621                var type;
34622                var steps;
34623                var realSteps;
34624                var stepSize;
34625                var isSteps = mode === "steps";
34626
34627                // When using 'steps' mode, use the provided steps.
34628                // Otherwise, we'll step on to the next subrange.
34629                if (isSteps) {
34630                    step = scope_Spectrum.xNumSteps[index];
34631                }
34632
34633                // Default to a 'full' step.
34634                if (!step) {
34635                    step = high - low;
34636                }
34637
34638                // Low can be 0, so test for false. If high is undefined,
34639                // we are at the last subrange. Index 0 is already handled.
34640                if (low === false || high === undefined) {
34641                    return;
34642                }
34643
34644                // Make sure step isn't 0, which would cause an infinite loop (#654)
34645                step = Math.max(step, 0.0000001);
34646
34647                // Find all steps in the subrange.
34648                for (i = low; i <= high; i = safeIncrement(i, step)) {
34649                    // Get the percentage value for the current step,
34650                    // calculate the size for the subrange.
34651                    newPct = scope_Spectrum.toStepping(i);
34652                    pctDifference = newPct - prevPct;
34653
34654                    steps = pctDifference / density;
34655                    realSteps = Math.round(steps);
34656
34657                    // This ratio represents the amount of percentage-space a point indicates.
34658                    // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided.
34659                    // Round the percentage offset to an even number, then divide by two
34660                    // to spread the offset on both sides of the range.
34661                    stepSize = pctDifference / realSteps;
34662
34663                    // Divide all points evenly, adding the correct number to this subrange.
34664                    // Run up to <= so that 100% gets a point, event if ignoreLast is set.
34665                    for (q = 1; q <= realSteps; q += 1) {
34666                        // The ratio between the rounded value and the actual size might be ~1% off.
34667                        // Correct the percentage offset by the number of points
34668                        // per subrange. density = 1 will result in 100 points on the
34669                        // full range, 2 for 50, 4 for 25, etc.
34670                        pctPos = prevPct + q * stepSize;
34671                        indexes[pctPos.toFixed(5)] = [scope_Spectrum.fromStepping(pctPos), 0];
34672                    }
34673
34674                    // Determine the point type.
34675                    type = group.indexOf(i) > -1 ? PIPS_LARGE_VALUE : isSteps ? PIPS_SMALL_VALUE : PIPS_NO_VALUE;
34676
34677                    // Enforce the 'ignoreFirst' option by overwriting the type for 0.
34678                    if (!index && ignoreFirst) {
34679                        type = 0;
34680                    }
34681
34682                    if (!(i === high && ignoreLast)) {
34683                        // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value.
34684                        indexes[newPct.toFixed(5)] = [i, type];
34685                    }
34686
34687                    // Update the percentage count.
34688                    prevPct = newPct;
34689                }
34690            });
34691
34692            return indexes;
34693        }
34694
34695        function addMarking(spread, filterFunc, formatter) {
34696            var element = scope_Document.createElement("div");
34697
34698            var valueSizeClasses = [];
34699            valueSizeClasses[PIPS_NO_VALUE] = options.cssClasses.valueNormal;
34700            valueSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.valueLarge;
34701            valueSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.valueSub;
34702
34703            var markerSizeClasses = [];
34704            markerSizeClasses[PIPS_NO_VALUE] = options.cssClasses.markerNormal;
34705            markerSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.markerLarge;
34706            markerSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.markerSub;
34707
34708            var valueOrientationClasses = [options.cssClasses.valueHorizontal, options.cssClasses.valueVertical];
34709            var markerOrientationClasses = [options.cssClasses.markerHorizontal, options.cssClasses.markerVertical];
34710
34711            addClass(element, options.cssClasses.pips);
34712            addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical);
34713
34714            function getClasses(type, source) {
34715                var a = source === options.cssClasses.value;
34716                var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses;
34717                var sizeClasses = a ? valueSizeClasses : markerSizeClasses;
34718
34719                return source + " " + orientationClasses[options.ort] + " " + sizeClasses[type];
34720            }
34721
34722            function addSpread(offset, value, type) {
34723                // Apply the filter function, if it is set.
34724                type = filterFunc ? filterFunc(value, type) : type;
34725
34726                if (type === PIPS_NONE) {
34727                    return;
34728                }
34729
34730                // Add a marker for every point
34731                var node = addNodeTo(element, false);
34732                node.className = getClasses(type, options.cssClasses.marker);
34733                node.style[options.style] = offset + "%";
34734
34735                // Values are only appended for points marked '1' or '2'.
34736                if (type > PIPS_NO_VALUE) {
34737                    node = addNodeTo(element, false);
34738                    node.className = getClasses(type, options.cssClasses.value);
34739                    node.setAttribute("data-value", value);
34740                    node.style[options.style] = offset + "%";
34741                    node.innerHTML = formatter.to(value);
34742                }
34743            }
34744
34745            // Append all points.
34746            Object.keys(spread).forEach(function(offset) {
34747                addSpread(offset, spread[offset][0], spread[offset][1]);
34748            });
34749
34750            return element;
34751        }
34752
34753        function removePips() {
34754            if (scope_Pips) {
34755                removeElement(scope_Pips);
34756                scope_Pips = null;
34757            }
34758        }
34759
34760        function pips(grid) {
34761            // Fix #669
34762            removePips();
34763
34764            var mode = grid.mode;
34765            var density = grid.density || 1;
34766            var filter = grid.filter || false;
34767            var values = grid.values || false;
34768            var stepped = grid.stepped || false;
34769            var group = getGroup(mode, values, stepped);
34770            var spread = generateSpread(density, mode, group);
34771            var format = grid.format || {
34772                to: Math.round
34773            };
34774
34775            scope_Pips = scope_Target.appendChild(addMarking(spread, filter, format));
34776
34777            return scope_Pips;
34778        }
34779
34780        // Shorthand for base dimensions.
34781        function baseSize() {
34782            var rect = scope_Base.getBoundingClientRect();
34783            var alt = "offset" + ["Width", "Height"][options.ort];
34784            return options.ort === 0 ? rect.width || scope_Base[alt] : rect.height || scope_Base[alt];
34785        }
34786
34787        // Handler for attaching events trough a proxy.
34788        function attachEvent(events, element, callback, data) {
34789            // This function can be used to 'filter' events to the slider.
34790            // element is a node, not a nodeList
34791
34792            var method = function(e) {
34793                e = fixEvent(e, data.pageOffset, data.target || element);
34794
34795                // fixEvent returns false if this event has a different target
34796                // when handling (multi-) touch events;
34797                if (!e) {
34798                    return false;
vendor: 15,307 bytes, lines 34799-35174
34799                }
34800
34801                // doNotReject is passed by all end events to make sure released touches
34802                // are not rejected, leaving the slider "stuck" to the cursor;
34803                if (scope_Target.hasAttribute("disabled") && !data.doNotReject) {
34804                    return false;
34805                }
34806
34807                // Stop if an active 'tap' transition is taking place.
34808                if (hasClass(scope_Target, options.cssClasses.tap) && !data.doNotReject) {
34809                    return false;
34810                }
34811
34812                // Ignore right or middle clicks on start #454
34813                if (events === actions.start && e.buttons !== undefined && e.buttons > 1) {
34814                    return false;
34815                }
34816
34817                // Ignore right or middle clicks on start #454
34818                if (data.hover && e.buttons) {
34819                    return false;
34820                }
34821
34822                // 'supportsPassive' is only true if a browser also supports touch-action: none in CSS.
34823                // iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support
34824                // touch-action: manipulation, but that allows panning, which breaks
34825                // sliders after zooming/on non-responsive pages.
34826                // See: https://bugs.webkit.org/show_bug.cgi?id=133112
34827                if (!supportsPassive) {
34828                    e.preventDefault();
34829                }
34830
34831                e.calcPoint = e.points[options.ort];
34832
34833                // Call the event handler with the event [ and additional data ].
34834                callback(e, data);
34835            };
34836
34837            var methods = [];
34838
34839            // Bind a closure on the target for every event type.
34840            events.split(" ").forEach(function(eventName) {
34841                element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false);
34842                methods.push([eventName, method]);
34843            });
34844
34845            return methods;
34846        }
34847
34848        // Provide a clean event with standardized offset values.
34849        function fixEvent(e, pageOffset, eventTarget) {
34850            // Filter the event to register the type, which can be
34851            // touch, mouse or pointer. Offset changes need to be
34852            // made on an event specific basis.
34853            var touch = e.type.indexOf("touch") === 0;
34854            var mouse = e.type.indexOf("mouse") === 0;
34855            var pointer = e.type.indexOf("pointer") === 0;
34856
34857            var x;
34858            var y;
34859
34860            // IE10 implemented pointer events with a prefix;
34861            if (e.type.indexOf("MSPointer") === 0) {
34862                pointer = true;
34863            }
34864
34865            // The only thing one handle should be concerned about is the touches that originated on top of it.
34866            if (touch) {
34867                // Returns true if a touch originated on the target.
34868                var isTouchOnTarget = function(checkTouch) {
34869                    return checkTouch.target === eventTarget || eventTarget.contains(checkTouch.target);
34870                };
34871
34872                // In the case of touchstart events, we need to make sure there is still no more than one
34873                // touch on the target so we look amongst all touches.
34874                if (e.type === "touchstart") {
34875                    var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget);
34876
34877                    // Do not support more than one touch per handle.
34878                    if (targetTouches.length > 1) {
34879                        return false;
34880                    }
34881
34882                    x = targetTouches[0].pageX;
34883                    y = targetTouches[0].pageY;
34884                } else {
34885                    // In the other cases, find on changedTouches is enough.
34886                    var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget);
34887
34888                    // Cancel if the target touch has not moved.
34889                    if (!targetTouch) {
34890                        return false;
34891                    }
34892
34893                    x = targetTouch.pageX;
34894                    y = targetTouch.pageY;
34895                }
34896            }
34897
34898            pageOffset = pageOffset || getPageOffset(scope_Document);
34899
34900            if (mouse || pointer) {
34901                x = e.clientX + pageOffset.x;
34902                y = e.clientY + pageOffset.y;
34903            }
34904
34905            e.pageOffset = pageOffset;
34906            e.points = [x, y];
34907            e.cursor = mouse || pointer; // Fix #435
34908
34909            return e;
34910        }
34911
34912        // Translate a coordinate in the document to a percentage on the slider
34913        function calcPointToPercentage(calcPoint) {
34914            var location = calcPoint - offset(scope_Base, options.ort);
34915            var proposal = (location * 100) / baseSize();
34916
34917            // Clamp proposal between 0% and 100%
34918            // Out-of-bound coordinates may occur when .noUi-base pseudo-elements
34919            // are used (e.g. contained handles feature)
34920            proposal = limit(proposal);
34921
34922            return options.dir ? 100 - proposal : proposal;
34923        }
34924
34925        // Find handle closest to a certain percentage on the slider
34926        function getClosestHandle(proposal) {
34927            var closest = 100;
34928            var handleNumber = false;
34929
34930            scope_Handles.forEach(function(handle, index) {
34931                // Disabled handles are ignored
34932                if (handle.hasAttribute("disabled")) {
34933                    return;
34934                }
34935
34936                var pos = Math.abs(scope_Locations[index] - proposal);
34937
34938                if (pos < closest || (pos === 100 && closest === 100)) {
34939                    handleNumber = index;
34940                    closest = pos;
34941                }
34942            });
34943
34944            return handleNumber;
34945        }
34946
34947        // Fire 'end' when a mouse or pen leaves the document.
34948        function documentLeave(event, data) {
34949            if (event.type === "mouseout" && event.target.nodeName === "HTML" && event.relatedTarget === null) {
34950                eventEnd(event, data);
34951            }
34952        }
34953
34954        // Handle movement on document for handle and range drag.
34955        function eventMove(event, data) {
34956            // Fix #498
34957            // Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty).
34958            // https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero
34959            // IE9 has .buttons and .which zero on mousemove.
34960            // Firefox breaks the spec MDN defines.
34961            if (navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0) {
34962                return eventEnd(event, data);
34963            }
34964
34965            // Check if we are moving up or down
34966            var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint);
34967
34968            // Convert the movement into a percentage of the slider width/height
34969            var proposal = (movement * 100) / data.baseSize;
34970
34971            moveHandles(movement > 0, proposal, data.locations, data.handleNumbers);
34972        }
34973
34974        // Unbind move events on document, call callbacks.
34975        function eventEnd(event, data) {
34976            // The handle is no longer active, so remove the class.
34977            if (data.handle) {
34978                removeClass(data.handle, options.cssClasses.active);
34979                scope_ActiveHandlesCount -= 1;
34980            }
34981
34982            // Unbind the move and end events, which are added on 'start'.
34983            data.listeners.forEach(function(c) {
34984                scope_DocumentElement.removeEventListener(c[0], c[1]);
34985            });
34986
34987            if (scope_ActiveHandlesCount === 0) {
34988                // Remove dragging class.
34989                removeClass(scope_Target, options.cssClasses.drag);
34990                setZindex();
34991
34992                // Remove cursor styles and text-selection events bound to the body.
34993                if (event.cursor) {
34994                    scope_Body.style.cursor = "";
34995                    scope_Body.removeEventListener("selectstart", preventDefault);
34996                }
34997            }
34998
34999            data.handleNumbers.forEach(function(handleNumber) {
35000                fireEvent("change", handleNumber);
35001                fireEvent("set", handleNumber);
35002                fireEvent("end", handleNumber);
35003            });
35004        }
35005
35006        // Bind move events on document.
35007        function eventStart(event, data) {
35008            var handle;
35009            if (data.handleNumbers.length === 1) {
35010                var handleOrigin = scope_Handles[data.handleNumbers[0]];
35011
35012                // Ignore 'disabled' handles
35013                if (handleOrigin.hasAttribute("disabled")) {
35014                    return false;
35015                }
35016
35017                handle = handleOrigin.children[0];
35018                scope_ActiveHandlesCount += 1;
35019
35020                // Mark the handle as 'active' so it can be styled.
35021                addClass(handle, options.cssClasses.active);
35022            }
35023
35024            // A drag should never propagate up to the 'tap' event.
35025            event.stopPropagation();
35026
35027            // Record the event listeners.
35028            var listeners = [];
35029
35030            // Attach the move and end events.
35031            var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, {
35032                // The event target has changed so we need to propagate the original one so that we keep
35033                // relying on it to extract target touches.
35034                target: event.target,
35035                handle: handle,
35036                listeners: listeners,
35037                startCalcPoint: event.calcPoint,
35038                baseSize: baseSize(),
35039                pageOffset: event.pageOffset,
35040                handleNumbers: data.handleNumbers,
35041                buttonsProperty: event.buttons,
35042                locations: scope_Locations.slice()
35043            });
35044
35045            var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, {
35046                target: event.target,
35047                handle: handle,
35048                listeners: listeners,
35049                doNotReject: true,
35050                handleNumbers: data.handleNumbers
35051            });
35052
35053            var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, {
35054                target: event.target,
35055                handle: handle,
35056                listeners: listeners,
35057                doNotReject: true,
35058                handleNumbers: data.handleNumbers
35059            });
35060
35061            // We want to make sure we pushed the listeners in the listener list rather than creating
35062            // a new one as it has already been passed to the event handlers.
35063            listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent));
35064
35065            // Text selection isn't an issue on touch devices,
35066            // so adding cursor styles can be skipped.
35067            if (event.cursor) {
35068                // Prevent the 'I' cursor and extend the range-drag cursor.
35069                scope_Body.style.cursor = getComputedStyle(event.target).cursor;
35070
35071                // Mark the target with a dragging state.
35072                if (scope_Handles.length > 1) {
35073                    addClass(scope_Target, options.cssClasses.drag);
35074                }
35075
35076                // Prevent text selection when dragging the handles.
35077                // In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move,
35078                // which is scroll blocking. The selectstart event is supported by FireFox starting from version 52,
35079                // meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there.
35080                // The 'cursor' flag is false.
35081                // See: http://caniuse.com/#search=selectstart
35082                scope_Body.addEventListener("selectstart", preventDefault, false);
35083            }
35084
35085            data.handleNumbers.forEach(function(handleNumber) {
35086                fireEvent("start", handleNumber);
35087            });
35088        }
35089
35090        // Move closest handle to tapped location.
35091        function eventTap(event) {
35092            // The tap event shouldn't propagate up
35093            event.stopPropagation();
35094
35095            var proposal = calcPointToPercentage(event.calcPoint);
35096            var handleNumber = getClosestHandle(proposal);
35097
35098            // Tackle the case that all handles are 'disabled'.
35099            if (handleNumber === false) {
35100                return false;
35101            }
35102
35103            // Flag the slider as it is now in a transitional state.
35104            // Transition takes a configurable amount of ms (default 300). Re-enable the slider after that.
35105            if (!options.events.snap) {
35106                addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
35107            }
35108
35109            setHandle(handleNumber, proposal, true, true);
35110
35111            setZindex();
35112
35113            fireEvent("slide", handleNumber, true);
35114            fireEvent("update", handleNumber, true);
35115            fireEvent("change", handleNumber, true);
35116            fireEvent("set", handleNumber, true);
35117
35118            if (options.events.snap) {
35119                eventStart(event, { handleNumbers: [handleNumber] });
35120            }
35121        }
35122
35123        // Fires a 'hover' event for a hovered mouse/pen position.
35124        function eventHover(event) {
35125            var proposal = calcPointToPercentage(event.calcPoint);
35126
35127            var to = scope_Spectrum.getStep(proposal);
35128            var value = scope_Spectrum.fromStepping(to);
35129
35130            Object.keys(scope_Events).forEach(function(targetEvent) {
35131                if ("hover" === targetEvent.split(".")[0]) {
35132                    scope_Events[targetEvent].forEach(function(callback) {
35133                        callback.call(scope_Self, value);
35134                    });
35135                }
35136            });
35137        }
35138
35139        // Attach events to several slider parts.
35140        function bindSliderEvents(behaviour) {
35141            // Attach the standard drag event to the handles.
35142            if (!behaviour.fixed) {
35143                scope_Handles.forEach(function(handle, index) {
35144                    // These events are only bound to the visual handle
35145                    // element, not the 'real' origin element.
35146                    attachEvent(actions.start, handle.children[0], eventStart, {
35147                        handleNumbers: [index]
35148                    });
35149                });
35150            }
35151
35152            // Attach the tap event to the slider base.
35153            if (behaviour.tap) {
35154                attachEvent(actions.start, scope_Base, eventTap, {});
35155            }
35156
35157            // Fire hover events
35158            if (behaviour.hover) {
35159                attachEvent(actions.move, scope_Base, eventHover, {
35160                    hover: true
35161                });
35162            }
35163
35164            // Make the range draggable.
35165            if (behaviour.drag) {
35166                scope_Connects.forEach(function(connect, index) {
35167                    if (connect === false || index === 0 || index === scope_Connects.length - 1) {
35168                        return;
35169                    }
35170
35171                    var handleBefore = scope_Handles[index - 1];
35172                    var handleAfter = scope_Handles[index];
35173                    var eventHolders = [connect];
35174
35175                    addClass(connect, options.cssClasses.draggable);
35176
35177                    // When the range is fixed, the entire range can
35178                    // be dragged by the handles. The handle in the first
35179                    // origin will propagate the start event upward,
35180                    // but it needs to be bound manually on the other.
35181                    if (behaviour.fixed) {
35182                        eventHolders.push(handleBefore.children[0]);
35183                        eventHolders.push(handleAfter.children[0]);
35184                    }
35185
35186                    eventHolders.forEach(function(eventHolder) {
35187                        attachEvent(actions.start, eventHolder, eventStart, {
35188                            handles: [handleBefore, handleAfter],
35189                            handleNumbers: [index - 1, index]
35190                        });
35191                    });
35192                });
35193            }
35194        }
35195
35196        // Attach an event to this slider, possibly including a namespace
35197        function bindEvent(namespacedEvent, callback) {
35198            scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || [];
35199            scope_Events[namespacedEvent].push(callback);
35200
35201            // If the event bound is 'update,' fire it immediately for all handles.
35202            if (namespacedEvent.split(".")[0] === "update") {
35203                scope_Handles.forEach(function(a, index) {
35204                    fireEvent("update", index);
35205                });
35206            }
35207        }
35208
35209        // Undo attachment of event
35210        function removeEvent(namespacedEvent) {
35211            var event = namespacedEvent && namespacedEvent.split(".")[0];
35212            var namespace = event && namespacedEvent.substring(event.length);
35213
35214            Object.keys(scope_Events).forEach(function(bind) {
35215                var tEvent = bind.split(".")[0];
35216                var tNamespace = bind.substring(tEvent.length);
35217
35218                if ((!event || event === tEvent) && (!namespace || namespace === tNamespace)) {
35219                    delete scope_Events[bind];
35220                }
35221            });
35222        }
35223
35224        // External event handling
35225        function fireEvent(eventName, handleNumber, tap) {
35226            Object.keys(scope_Events).forEach(function(targetEvent) {
35227                var eventType = targetEvent.split(".")[0];
35228
35229                if (eventName === eventType) {
35230                    scope_Events[targetEvent].forEach(function(callback) {
35231                        callback.call(
35232                            // Use the slider public API as the scope ('this')
35233                            scope_Self,
35234                            // Return values as array, so arg_1[arg_2] is always valid.
35235                            scope_Values.map(options.format.to),
35236                            // Handle index, 0 or 1
35237                            handleNumber,
35238                            // Un-formatted slider values
35239                            scope_Values.slice(),
35240                            // Event is fired by tap, true or false
35241                            tap || false,
35242                            // Left offset of the handle, in relation to the slider
35243                            scope_Locations.slice()
35244                        );
35245                    });
35246                }
35247            });
35248        }
35249
35250        function toPct(pct) {
35251            return pct + "%";
35252        }
35253
35254        // Split out the handle positioning logic so the Move event can use it, too
35255        function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue) {
35256            // For sliders with multiple handles, limit movement to the other handle.
35257            // Apply the margin option by adding it to the handle positions.
35258            if (scope_Handles.length > 1 && !options.events.unconstrained) {
35259                if (lookBackward && handleNumber > 0) {
35260                    to = Math.max(to, reference[handleNumber - 1] + options.margin);
35261                }
35262
35263                if (lookForward && handleNumber < scope_Handles.length - 1) {
35264                    to = Math.min(to, reference[handleNumber + 1] - options.margin);
35265                }
35266            }
35267
35268            // The limit option has the opposite effect, limiting handles to a
35269            // maximum distance from another. Limit must be > 0, as otherwise
35270            // handles would be unmovable.
35271            if (scope_Handles.length > 1 && options.limit) {
35272                if (lookBackward && handleNumber > 0) {
35273                    to = Math.min(to, reference[handleNumber - 1] + options.limit);
35274                }
35275
35276                if (lookForward && handleNumber < scope_Handles.length - 1) {
35277                    to = Math.max(to, reference[handleNumber + 1] - options.limit);
35278                }
35279            }
35280
35281            // The padding option keeps the handles a certain distance from the
35282            // edges of the slider. Padding must be > 0.
35283            if (options.padding) {
35284                if (handleNumber === 0) {
35285                    to = Math.max(to, options.padding[0]);
35286                }
35287
35288                if (handleNumber === scope_Handles.length - 1) {
35289                    to = Math.min(to, 100 - options.padding[1]);
35290                }
35291            }
35292
35293            to = scope_Spectrum.getStep(to);
35294
35295            // Limit percentage to the 0 - 100 range
35296            to = limit(to);
35297
35298            // Return false if handle can't move
35299            if (to === reference[handleNumber] && !getValue) {
35300                return false;
35301            }
35302
35303            return to;
35304        }
35305
35306        // Uses slider orientation to create CSS rules. a = base value;
35307        function inRuleOrder(v, a) {
35308            var o = options.ort;
35309            return (o ? a : v) + ", " + (o ? v : a);
35310        }
35311
35312        // Moves handle(s) by a percentage
35313        // (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...])
35314        function moveHandles(upward, proposal, locations, handleNumbers) {
35315            var proposals = locations.slice();
35316
35317            var b = [!upward, upward];
35318            var f = [upward, !upward];
35319
35320            // Copy handleNumbers so we don't change the dataset
35321            handleNumbers = handleNumbers.slice();
35322
35323            // Check to see which handle is 'leading'.
35324            // If that one can't move the second can't either.
35325            if (upward) {
35326                handleNumbers.reverse();
35327            }
35328
35329            // Step 1: get the maximum percentage that any of the handles can move
35330            if (handleNumbers.length > 1) {
35331                handleNumbers.forEach(function(handleNumber, o) {
35332                    var to = checkHandlePosition(
35333                        proposals,
35334                        handleNumber,
35335                        proposals[handleNumber] + proposal,
35336                        b[o],
35337                        f[o],
35338                        false
35339                    );
35340
35341                    // Stop if one of the handles can't move.
35342                    if (to === false) {
35343                        proposal = 0;
35344                    } else {
35345                        proposal = to - proposals[handleNumber];
35346                        proposals[handleNumber] = to;
35347                    }
35348                });
35349            }
35350
35351            // If using one handle, check backward AND forward
35352            else {
35353                b = f = [true];
35354            }
35355
35356            var state = false;
35357
35358            // Step 2: Try to set the handles with the found percentage
35359            handleNumbers.forEach(function(handleNumber, o) {
35360                state = setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o]) || state;
35361            });
35362
35363            // Step 3: If a handle moved, fire events
35364            if (state) {
35365                handleNumbers.forEach(function(handleNumber) {
35366                    fireEvent("update", handleNumber);
35367                    fireEvent("slide", handleNumber);
35368                });
35369            }
35370        }
35371
35372        // Takes a base value and an offset. This offset is used for the connect bar size.
35373        // In the initial design for this feature, the origin element was 1% wide.
35374        // Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature
35375        // in this manner: https://bugs.chromium.org/p/chromium/issues/detail?id=798223
35376        function transformDirection(a, b) {
35377            return options.dir ? 100 - a - b : a;
35378        }
35379
35380        // Updates scope_Locations and scope_Values, updates visual state
35381        function updateHandlePosition(handleNumber, to) {
35382            // Update locations.
35383            scope_Locations[handleNumber] = to;
35384
35385            // Convert the value to the slider stepping/range.
35386            scope_Values[handleNumber] = scope_Spectrum.fromStepping(to);
35387
35388            var rule = "translate(" + inRuleOrder(toPct(transformDirection(to, 0) - scope_DirOffset), "0") + ")";
35389            scope_Handles[handleNumber].style[options.transformRule] = rule;
35390
35391            updateConnect(handleNumber);
35392            updateConnect(handleNumber + 1);
35393        }
35394
35395        // Handles before the slider middle are stacked later = higher,
35396        // Handles after the middle later is lower
35397        // [[7] [8] .......... | .......... [5] [4]
35398        function setZindex() {
35399            scope_HandleNumbers.forEach(function(handleNumber) {
35400                var dir = scope_Locations[handleNumber] > 50 ? -1 : 1;
35401                var zIndex = 3 + (scope_Handles.length + dir * handleNumber);
35402                scope_Handles[handleNumber].style.zIndex = zIndex;
35403            });
35404        }
35405
35406        // Test suggested values and apply margin, step.
35407        function setHandle(handleNumber, to, lookBackward, lookForward) {
35408            to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false);
35409
35410            if (to === false) {
35411                return false;
35412            }
35413
35414            updateHandlePosition(handleNumber, to);
35415
35416            return true;
35417        }
35418
35419        // Updates style attribute for connect nodes
35420        function updateConnect(index) {
35421            // Skip connects set to false
35422            if (!scope_Connects[index]) {
35423                return;
35424            }
35425
35426            var l = 0;
35427            var h = 100;
35428
35429            if (index !== 0) {
35430                l = scope_Locations[index - 1];
35431            }
35432
35433            if (index !== scope_Connects.length - 1) {
35434                h = scope_Locations[index];
35435            }
35436
35437            // We use two rules:
35438            // 'translate' to change the left/top offset;
35439            // 'scale' to change the width of the element;
35440            // As the element has a width of 100%, a translation of 100% is equal to 100% of the parent (.noUi-base)
35441            var connectWidth = h - l;
35442            var translateRule = "translate(" + inRuleOrder(toPct(transformDirection(l, connectWidth)), "0") + ")";
35443            var scaleRule = "scale(" + inRuleOrder(connectWidth / 100, "1") + ")";
35444
35445            scope_Connects[index].style[options.transformRule] = translateRule + " " + scaleRule;
35446        }
35447
35448        // Parses value passed to .set method. Returns current value if not parse-able.
35449        function resolveToValue(to, handleNumber) {
35450            // Setting with null indicates an 'ignore'.
35451            // Inputting 'false' is invalid.
35452            if (to === null || to === false || to === undefined) {
35453                return scope_Locations[handleNumber];
35454            }
35455
35456            // If a formatted number was passed, attempt to decode it.
35457            if (typeof to === "number") {
35458                to = String(to);
35459            }
35460
35461            to = options.format.from(to);
35462            to = scope_Spectrum.toStepping(to);
35463
35464            // If parsing the number failed, use the current value.
35465            if (to === false || isNaN(to)) {
35466                return scope_Locations[handleNumber];
35467            }
35468
35469            return to;
35470        }
35471
35472        // Set the slider value.
35473        function valueSet(input, fireSetEvent) {
35474            var values = asArray(input);
35475            var isInit = scope_Locations[0] === undefined;
35476
35477            // Event fires by default
35478            fireSetEvent = fireSetEvent === undefined ? true : !!fireSetEvent;
35479
35480            // Animation is optional.
35481            // Make sure the initial values were set before using animated placement.
35482            if (options.animate && !isInit) {
35483                addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
35484            }
35485
35486            // First pass, without lookAhead but with lookBackward. Values are set from left to right.
35487            scope_HandleNumbers.forEach(function(handleNumber) {
35488                setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false);
35489            });
35490
35491            // Second pass. Now that all base values are set, apply constraints
35492            scope_HandleNumbers.forEach(function(handleNumber) {
35493                setHandle(handleNumber, scope_Locations[handleNumber], true, true);
35494            });
35495
35496            setZindex();
35497
35498            scope_HandleNumbers.forEach(function(handleNumber) {
35499                fireEvent("update", handleNumber);
35500
35501                // Fire the event only for handles that received a new value, as per #579
35502                if (values[handleNumber] !== null && fireSetEvent) {
35503                    fireEvent("set", handleNumber);
35504                }
35505            });
35506        }
35507
35508        // Reset slider to initial values
35509        function valueReset(fireSetEvent) {
35510            valueSet(options.start, fireSetEvent);
35511        }
35512
35513        // Set value for a single handle
35514        function valueSetHandle(handleNumber, value, fireSetEvent) {
35515            var values = [];
35516
35517            // Ensure numeric input
35518            handleNumber = Number(handleNumber);
35519
35520            if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) {
35521                throw new Error("noUiSlider (" + VERSION + "): invalid handle number, got: " + handleNumber);
35522            }
35523
35524            for (var i = 0; i < scope_HandleNumbers.length; i++) {
35525                values[i] = null;
35526            }
35527
35528            values[handleNumber] = value;
35529
35530            valueSet(values, fireSetEvent);
35531        }
35532
35533        // Get the slider value.
35534        function valueGet() {
35535            var values = scope_Values.map(options.format.to);
35536
35537            // If only one handle is used, return a single value.
35538            if (values.length === 1) {
35539                return values[0];
35540            }
35541
35542            return values;
35543        }
35544
35545        // Removes classes from the root and empties it.
35546        function destroy() {
35547            for (var key in options.cssClasses) {
35548                if (!options.cssClasses.hasOwnProperty(key)) {
35549                    continue;
35550                }
35551                removeClass(scope_Target, options.cssClasses[key]);
35552            }
35553
35554            while (scope_Target.firstChild) {
35555                scope_Target.removeChild(scope_Target.firstChild);
35556            }
35557
35558            delete scope_Target.noUiSlider;
35559        }
35560
35561        // Get the current step size for the slider.
35562        function getCurrentStep() {
35563            // Check all locations, map them to their stepping point.
35564            // Get the step point, then find it in the input list.
35565            return scope_Locations.map(function(location, index) {
35566                var nearbySteps = scope_Spectrum.getNearbySteps(location);
35567                var value = scope_Values[index];
35568                var increment = nearbySteps.thisStep.step;
35569                var decrement = null;
35570
35571                // If the next value in this step moves into the next step,
35572                // the increment is the start of the next step - the current value
35573                if (increment !== false) {
35574                    if (value + increment > nearbySteps.stepAfter.startValue) {
35575                        increment = nearbySteps.stepAfter.startValue - value;
35576                    }
35577                }
35578
35579                // If the value is beyond the starting point
35580                if (value > nearbySteps.thisStep.startValue) {
35581                    decrement = nearbySteps.thisStep.step;
35582                } else if (nearbySteps.stepBefore.step === false) {
35583                    decrement = false;
35584                }
35585
35586                // If a handle is at the start of a step, it always steps back into the previous step first
35587                else {
35588                    decrement = value - nearbySteps.stepBefore.highestStep;
35589                }
35590
35591                // Now, if at the slider edges, there is not in/decrement
35592                if (location === 100) {
35593                    increment = null;
35594                } else if (location === 0) {
35595                    decrement = null;
35596                }
35597
35598                // As per #391, the comparison for the decrement step can have some rounding issues.
35599                var stepDecimals = scope_Spectrum.countStepDecimals();
35600
35601                // Round per #391
35602                if (increment !== null && increment !== false) {
35603                    increment = Number(increment.toFixed(stepDecimals));
35604                }
35605
35606                if (decrement !== null && decrement !== false) {
35607                    decrement = Number(decrement.toFixed(stepDecimals));
35608                }
35609
35610                return [decrement, increment];
35611            });
35612        }
35613
35614        // Updateable: margin, limit, padding, step, range, animate, snap
35615        function updateOptions(optionsToUpdate, fireSetEvent) {
35616            // Spectrum is created using the range, snap, direction and step options.
35617            // 'snap' and 'step' can be updated.
35618            // If 'snap' and 'step' are not passed, they should remain unchanged.
35619            var v = valueGet();
35620
35621            var updateAble = ["margin", "limit", "padding", "range", "animate", "snap", "step", "format"];
35622
35623            // Only change options that we're actually passed to update.
35624            updateAble.forEach(function(name) {
35625                if (optionsToUpdate[name] !== undefined) {
35626                    originalOptions[name] = optionsToUpdate[name];
35627                }
35628            });
35629
35630            var newOptions = testOptions(originalOptions);
35631
35632            // Load new options into the slider state
35633            updateAble.forEach(function(name) {
35634                if (optionsToUpdate[name] !== undefined) {
35635                    options[name] = newOptions[name];
35636                }
35637            });
35638
35639            scope_Spectrum = newOptions.spectrum;
35640
35641            // Limit, margin and padding depend on the spectrum but are stored outside of it. (#677)
35642            options.margin = newOptions.margin;
35643            options.limit = newOptions.limit;
35644            options.padding = newOptions.padding;
35645
35646            // Update pips, removes existing.
35647            if (options.pips) {
35648                pips(options.pips);
35649            }
35650
35651            // Invalidate the current positioning so valueSet forces an update.
35652            scope_Locations = [];
35653            valueSet(optionsToUpdate.start || v, fireSetEvent);
35654        }
35655
35656        // Create the base element, initialize HTML and set classes.
35657        // Add handles and connect elements.
35658        scope_Base = addSlider(scope_Target);
35659        addElements(options.connect, scope_Base);
35660
35661        // Attach user events.
35662        bindSliderEvents(options.events);
35663
35664        // Use the public value method to set the start values.
35665        valueSet(options.start);
35666
35667        // noinspection JSUnusedGlobalSymbols
35668        scope_Self = {
35669            destroy: destroy,
35670            steps: getCurrentStep,
35671            on: bindEvent,
35672            off: removeEvent,
35673            get: valueGet,
35674            set: valueSet,
35675            setHandle: valueSetHandle,
35676            reset: valueReset,
35677            // Exposed for unit testing, don't use this in your application.
35678            __moveHandles: function(a, b, c) {
35679                moveHandles(a, b, scope_Locations, c);
35680            },
35681            options: originalOptions, // Issue #600, #678
35682            updateOptions: updateOptions,
35683            target: scope_Target, // Issue #597
35684            removePips: removePips,
35685            pips: pips // Issue #594
35686        };
35687
35688        if (options.pips) {
35689            pips(options.pips);
35690        }
35691
35692        if (options.tooltips) {
35693            tooltips();
35694        }
35695
35696        aria();
35697
35698        return scope_Self;
35699    }
35700
35701    // Run the standard initializer
35702    function initialize(target, originalOptions) {
35703        if (!target || !target.nodeName) {
35704            throw new Error("noUiSlider (" + VERSION + "): create requires a single element, got: " + target);
35705        }
35706
35707        // Throw an error if the slider was already initialized.
35708        if (target.noUiSlider) {
35709            throw new Error("noUiSlider (" + VERSION + "): Slider was already initialized.");
35710        }
35711
35712        // Test the options and create the slider environment;
35713        var options = testOptions(originalOptions, target);
35714        var api = scope(target, options, originalOptions);
35715
35716        target.noUiSlider = api;
35717
35718        return api;
35719    }
35720
35721    // Use an object instead of a function for future expandability;
35722    return {
35723        // Exposed for unit testing, don't use this in your application.
35724        __spectrum: Spectrum,
35725        version: VERSION,
35726        create: initialize
35727    };
35728});
35729
vendor: 89,992 bytes, lines 35730-39177
35730/**
35731 * Owl Carousel v2.3.4
35732 * Copyright 2013-2018 David Deutsch
35733 * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
35734 */
35735/**
35736 * Owl carousel
35737 * @version 2.3.4
35738 * @author Bartosz Wojciechowski
35739 * @author David Deutsch
35740 * @license The MIT License (MIT)
35741 * @todo Lazy Load Icon
35742 * @todo prevent animationend bubling
35743 * @todo itemsScaleUp
35744 * @todo Test Zepto
35745 * @todo stagePadding calculate wrong active classes
35746 */
35747;(function($, window, document, undefined) {
35748
35749	/**
35750	 * Creates a carousel.
35751	 * @class The Owl Carousel.
35752	 * @public
35753	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
35754	 * @param {Object} [options] - The options
35755	 */
35756	function Owl(element, options) {
35757
35758		/**
35759		 * Current settings for the carousel.
35760		 * @public
35761		 */
35762		this.settings = null;
35763
35764		/**
35765		 * Current options set by the caller including defaults.
35766		 * @public
35767		 */
35768		this.options = $.extend({}, Owl.Defaults, options);
35769
35770		/**
35771		 * Plugin element.
35772		 * @public
35773		 */
35774		this.$element = $(element);
35775
35776		/**
35777		 * Proxied event handlers.
35778		 * @protected
35779		 */
35780		this._handlers = {};
35781
35782		/**
35783		 * References to the running plugins of this carousel.
35784		 * @protected
35785		 */
35786		this._plugins = {};
35787
35788		/**
35789		 * Currently suppressed events to prevent them from being retriggered.
35790		 * @protected
35791		 */
35792		this._supress = {};
35793
35794		/**
35795		 * Absolute current position.
35796		 * @protected
35797		 */
35798		this._current = null;
35799
35800		/**
35801		 * Animation speed in milliseconds.
35802		 * @protected
35803		 */
35804		this._speed = null;
35805
35806		/**
35807		 * Coordinates of all items in pixel.
35808		 * @todo The name of this member is missleading.
35809		 * @protected
35810		 */
35811		this._coordinates = [];
35812
35813		/**
35814		 * Current breakpoint.
35815		 * @todo Real media queries would be nice.
35816		 * @protected
35817		 */
35818		this._breakpoint = null;
35819
35820		/**
35821		 * Current width of the plugin element.
35822		 */
35823		this._width = null;
35824
35825		/**
35826		 * All real items.
35827		 * @protected
35828		 */
35829		this._items = [];
35830
35831		/**
35832		 * All cloned items.
35833		 * @protected
35834		 */
35835		this._clones = [];
35836
35837		/**
35838		 * Merge values of all items.
35839		 * @todo Maybe this could be part of a plugin.
35840		 * @protected
35841		 */
35842		this._mergers = [];
35843
35844		/**
35845		 * Widths of all items.
35846		 */
35847		this._widths = [];
35848
35849		/**
35850		 * Invalidated parts within the update process.
35851		 * @protected
35852		 */
35853		this._invalidated = {};
35854
35855		/**
35856		 * Ordered list of workers for the update process.
35857		 * @protected
35858		 */
35859		this._pipe = [];
35860
35861		/**
35862		 * Current state information for the drag operation.
35863		 * @todo #261
35864		 * @protected
35865		 */
35866		this._drag = {
35867			time: null,
35868			target: null,
35869			pointer: null,
35870			stage: {
35871				start: null,
35872				current: null
35873			},
35874			direction: null
35875		};
35876
35877		/**
35878		 * Current state information and their tags.
35879		 * @type {Object}
35880		 * @protected
35881		 */
35882		this._states = {
35883			current: {},
35884			tags: {
35885				'initializing': [ 'busy' ],
35886				'animating': [ 'busy' ],
35887				'dragging': [ 'interacting' ]
35888			}
35889		};
35890
35891		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
35892			this._handlers[handler] = $.proxy(this[handler], this);
35893		}, this));
35894
35895		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
35896			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
35897				= new plugin(this);
35898		}, this));
35899
35900		$.each(Owl.Workers, $.proxy(function(priority, worker) {
35901			this._pipe.push({
35902				'filter': worker.filter,
35903				'run': $.proxy(worker.run, this)
35904			});
35905		}, this));
35906
35907		this.setup();
35908		this.initialize();
35909	}
35910
35911	/**
35912	 * Default options for the carousel.
35913	 * @public
35914	 */
35915	Owl.Defaults = {
35916		items: 3,
35917		loop: false,
35918		center: false,
35919		rewind: false,
35920		checkVisibility: true,
35921
35922		mouseDrag: true,
35923		touchDrag: true,
35924		pullDrag: true,
35925		freeDrag: false,
35926
35927		margin: 0,
35928		stagePadding: 0,
35929
35930		merge: false,
35931		mergeFit: true,
35932		autoWidth: false,
35933
35934		startPosition: 0,
35935		rtl: false,
35936
35937		smartSpeed: 250,
35938		fluidSpeed: false,
35939		dragEndSpeed: false,
35940
35941		responsive: {},
35942		responsiveRefreshRate: 200,
35943		responsiveBaseElement: window,
35944
35945		fallbackEasing: 'swing',
35946		slideTransition: '',
35947
35948		info: false,
35949
35950		nestedItemSelector: false,
35951		itemElement: 'div',
35952		stageElement: 'div',
35953
35954		refreshClass: 'owl-refresh',
35955		loadedClass: 'owl-loaded',
35956		loadingClass: 'owl-loading',
35957		rtlClass: 'owl-rtl',
35958		responsiveClass: 'owl-responsive',
35959		dragClass: 'owl-drag',
35960		itemClass: 'owl-item',
35961		stageClass: 'owl-stage',
35962		stageOuterClass: 'owl-stage-outer',
35963		grabClass: 'owl-grab'
35964	};
35965
35966	/**
35967	 * Enumeration for width.
35968	 * @public
35969	 * @readonly
35970	 * @enum {String}
35971	 */
35972	Owl.Width = {
35973		Default: 'default',
35974		Inner: 'inner',
35975		Outer: 'outer'
35976	};
35977
35978	/**
35979	 * Enumeration for types.
35980	 * @public
35981	 * @readonly
35982	 * @enum {String}
35983	 */
35984	Owl.Type = {
35985		Event: 'event',
35986		State: 'state'
35987	};
35988
35989	/**
35990	 * Contains all registered plugins.
35991	 * @public
35992	 */
35993	Owl.Plugins = {};
35994
35995	/**
35996	 * List of workers involved in the update process.
35997	 */
35998	Owl.Workers = [ {
35999		filter: [ 'width', 'settings' ],
36000		run: function() {
36001			this._width = this.$element.width();
36002		}
36003	}, {
36004		filter: [ 'width', 'items', 'settings' ],
36005		run: function(cache) {
36006			cache.current = this._items && this._items[this.relative(this._current)];
36007		}
36008	}, {
36009		filter: [ 'items', 'settings' ],
36010		run: function() {
36011			this.$stage.children('.cloned').remove();
36012		}
36013	}, {
36014		filter: [ 'width', 'items', 'settings' ],
36015		run: function(cache) {
36016			var margin = this.settings.margin || '',
36017				grid = !this.settings.autoWidth,
36018				rtl = this.settings.rtl,
36019				css = {
36020					'width': 'auto',
36021					'margin-left': rtl ? margin : '',
36022					'margin-right': rtl ? '' : margin
36023				};
36024
36025			!grid && this.$stage.children().css(css);
36026
36027			cache.css = css;
36028		}
36029	}, {
36030		filter: [ 'width', 'items', 'settings' ],
36031		run: function(cache) {
36032			var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
36033				merge = null,
36034				iterator = this._items.length,
36035				grid = !this.settings.autoWidth,
36036				widths = [];
36037
36038			cache.items = {
36039				merge: false,
36040				width: width
36041			};
36042
36043			while (iterator--) {
36044				merge = this._mergers[iterator];
36045				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
36046
36047				cache.items.merge = merge > 1 || cache.items.merge;
36048
36049				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
36050			}
36051
36052			this._widths = widths;
36053		}
36054	}, {
36055		filter: [ 'items', 'settings' ],
36056		run: function() {
36057			var clones = [],
36058				items = this._items,
36059				settings = this.settings,
36060				// TODO: Should be computed from number of min width items in stage
36061				view = Math.max(settings.items * 2, 4),
36062				size = Math.ceil(items.length / 2) * 2,
36063				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
36064				append = '',
36065				prepend = '';
36066
36067			repeat /= 2;
36068
36069			while (repeat > 0) {
36070				// Switch to only using appended clones
36071				clones.push(this.normalize(clones.length / 2, true));
36072				append = append + items[clones[clones.length - 1]][0].outerHTML;
36073				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
36074				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
36075				repeat -= 1;
36076			}
36077
36078			this._clones = clones;
36079
36080			$(append).addClass('cloned').appendTo(this.$stage);
36081			$(prepend).addClass('cloned').prependTo(this.$stage);
36082		}
36083	}, {
36084		filter: [ 'width', 'items', 'settings' ],
36085		run: function() {
36086			var rtl = this.settings.rtl ? 1 : -1,
36087				size = this._clones.length + this._items.length,
36088				iterator = -1,
36089				previous = 0,
36090				current = 0,
36091				coordinates = [];
36092
36093			while (++iterator < size) {
36094				previous = coordinates[iterator - 1] || 0;
36095				current = this._widths[this.relative(iterator)] + this.settings.margin;
36096				coordinates.push(previous + current * rtl);
36097			}
36098
36099			this._coordinates = coordinates;
36100		}
36101	}, {
36102		filter: [ 'width', 'items', 'settings' ],
36103		run: function() {
36104			var padding = this.settings.stagePadding,
36105				coordinates = this._coordinates,
36106				css = {
36107					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
36108					'padding-left': padding || '',
36109					'padding-right': padding || ''
36110				};
36111
36112			this.$stage.css(css);
36113		}
36114	}, {
36115		filter: [ 'width', 'items', 'settings' ],
36116		run: function(cache) {
36117			var iterator = this._coordinates.length,
36118				grid = !this.settings.autoWidth,
36119				items = this.$stage.children();
36120
36121			if (grid && cache.items.merge) {
36122				while (iterator--) {
36123					cache.css.width = this._widths[this.relative(iterator)];
36124					items.eq(iterator).css(cache.css);
36125				}
36126			} else if (grid) {
36127				cache.css.width = cache.items.width;
36128				items.css(cache.css);
36129			}
36130		}
36131	}, {
36132		filter: [ 'items' ],
36133		run: function() {
36134			this._coordinates.length < 1 && this.$stage.removeAttr('style');
36135		}
36136	}, {
36137		filter: [ 'width', 'items', 'settings' ],
36138		run: function(cache) {
36139			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
36140			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
36141			this.reset(cache.current);
36142		}
36143	}, {
36144		filter: [ 'position' ],
36145		run: function() {
36146			this.animate(this.coordinates(this._current));
36147		}
36148	}, {
36149		filter: [ 'width', 'position', 'items', 'settings' ],
36150		run: function() {
36151			var rtl = this.settings.rtl ? 1 : -1,
36152				padding = this.settings.stagePadding * 2,
36153				begin = this.coordinates(this.current()) + padding,
36154				end = begin + this.width() * rtl,
36155				inner, outer, matches = [], i, n;
36156
36157			for (i = 0, n = this._coordinates.length; i < n; i++) {
36158				inner = this._coordinates[i - 1] || 0;
36159				outer = Math.abs(this._coordinates[i]) + padding * rtl;
36160
36161				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
36162					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
36163					matches.push(i);
36164				}
36165			}
36166
36167			this.$stage.children('.active').removeClass('active');
36168			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
36169
36170			this.$stage.children('.center').removeClass('center');
36171			if (this.settings.center) {
36172				this.$stage.children().eq(this.current()).addClass('center');
36173			}
36174		}
36175	} ];
36176
36177	/**
36178	 * Create the stage DOM element
36179	 */
36180	Owl.prototype.initializeStage = function() {
36181		this.$stage = this.$element.find('.' + this.settings.stageClass);
36182
36183		// if the stage is already in the DOM, grab it and skip stage initialization
36184		if (this.$stage.length) {
36185			return;
36186		}
36187
36188		this.$element.addClass(this.options.loadingClass);
36189
36190		// create stage
36191		this.$stage = $('<' + this.settings.stageElement + '>', {
36192			"class": this.settings.stageClass
36193		}).wrap( $( '<div/>', {
36194			"class": this.settings.stageOuterClass
36195		}));
36196
36197		// append stage
36198		this.$element.append(this.$stage.parent());
36199	};
36200
36201	/**
36202	 * Create item DOM elements
36203	 */
36204	Owl.prototype.initializeItems = function() {
36205		var $items = this.$element.find('.owl-item');
36206
36207		// if the items are already in the DOM, grab them and skip item initialization
36208		if ($items.length) {
36209			this._items = $items.get().map(function(item) {
36210				return $(item);
36211			});
36212
36213			this._mergers = this._items.map(function() {
36214				return 1;
36215			});
36216
36217			this.refresh();
36218
36219			return;
36220		}
36221
36222		// append content
36223		this.replace(this.$element.children().not(this.$stage.parent()));
36224
36225		// check visibility
36226		if (this.isVisible()) {
36227			// update view
36228			this.refresh();
36229		} else {
36230			// invalidate width
36231			this.invalidate('width');
36232		}
36233
36234		this.$element
36235			.removeClass(this.options.loadingClass)
36236			.addClass(this.options.loadedClass);
36237	};
36238
36239	/**
36240	 * Initializes the carousel.
36241	 * @protected
36242	 */
36243	Owl.prototype.initialize = function() {
36244		this.enter('initializing');
36245		this.trigger('initialize');
36246
36247		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
36248
36249		if (this.settings.autoWidth && !this.is('pre-loading')) {
36250			var imgs, nestedSelector, width;
36251			imgs = this.$element.find('img');
36252			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
36253			width = this.$element.children(nestedSelector).width();
36254
36255			if (imgs.length && width <= 0) {
36256				this.preloadAutoWidthImages(imgs);
36257			}
36258		}
36259
36260		this.initializeStage();
36261		this.initializeItems();
36262
36263		// register event handlers
36264		this.registerEventHandlers();
36265
36266		this.leave('initializing');
36267		this.trigger('initialized');
36268	};
36269
36270	/**
36271	 * @returns {Boolean} visibility of $element
36272	 *                    if you know the carousel will always be visible you can set `checkVisibility` to `false` to
36273	 *                    prevent the expensive browser layout forced reflow the $element.is(':visible') does
36274	 */
36275	Owl.prototype.isVisible = function() {
36276		return this.settings.checkVisibility
36277			? this.$element.is(':visible')
36278			: true;
36279	};
36280
36281	/**
36282	 * Setups the current settings.
36283	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
36284	 * @todo Support for media queries by using `matchMedia` would be nice.
36285	 * @public
36286	 */
36287	Owl.prototype.setup = function() {
36288		var viewport = this.viewport(),
36289			overwrites = this.options.responsive,
36290			match = -1,
36291			settings = null;
36292
36293		if (!overwrites) {
36294			settings = $.extend({}, this.options);
36295		} else {
36296			$.each(overwrites, function(breakpoint) {
36297				if (breakpoint <= viewport && breakpoint > match) {
36298					match = Number(breakpoint);
36299				}
36300			});
36301
36302			settings = $.extend({}, this.options, overwrites[match]);
36303			if (typeof settings.stagePadding === 'function') {
36304				settings.stagePadding = settings.stagePadding();
36305			}
36306			delete settings.responsive;
36307
36308			// responsive class
36309			if (settings.responsiveClass) {
36310				this.$element.attr('class',
36311					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
36312				);
36313			}
36314		}
36315
36316		this.trigger('change', { property: { name: 'settings', value: settings } });
36317		this._breakpoint = match;
36318		this.settings = settings;
36319		this.invalidate('settings');
36320		this.trigger('changed', { property: { name: 'settings', value: this.settings } });
36321	};
36322
36323	/**
36324	 * Updates option logic if necessery.
36325	 * @protected
36326	 */
36327	Owl.prototype.optionsLogic = function() {
36328		if (this.settings.autoWidth) {
36329			this.settings.stagePadding = false;
36330			this.settings.merge = false;
36331		}
36332	};
36333
36334	/**
36335	 * Prepares an item before add.
36336	 * @todo Rename event parameter `content` to `item`.
36337	 * @protected
36338	 * @returns {jQuery|HTMLElement} - The item container.
36339	 */
36340	Owl.prototype.prepare = function(item) {
36341		var event = this.trigger('prepare', { content: item });
36342
36343		if (!event.data) {
36344			event.data = $('<' + this.settings.itemElement + '/>')
36345				.addClass(this.options.itemClass).append(item)
36346		}
36347
36348		this.trigger('prepared', { content: event.data });
36349
36350		return event.data;
36351	};
36352
36353	/**
36354	 * Updates the view.
36355	 * @public
36356	 */
36357	Owl.prototype.update = function() {
36358		var i = 0,
36359			n = this._pipe.length,
36360			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
36361			cache = {};
36362
36363		while (i < n) {
36364			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
36365				this._pipe[i].run(cache);
36366			}
36367			i++;
36368		}
36369
36370		this._invalidated = {};
36371
36372		!this.is('valid') && this.enter('valid');
36373	};
36374
36375	/**
36376	 * Gets the width of the view.
36377	 * @public
36378	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
36379	 * @returns {Number} - The width of the view in pixel.
36380	 */
36381	Owl.prototype.width = function(dimension) {
36382		dimension = dimension || Owl.Width.Default;
36383		switch (dimension) {
36384			case Owl.Width.Inner:
36385			case Owl.Width.Outer:
36386				return this._width;
36387			default:
36388				return this._width - this.settings.stagePadding * 2 + this.settings.margin;
36389		}
36390	};
36391
36392	/**
36393	 * Refreshes the carousel primarily for adaptive purposes.
36394	 * @public
36395	 */
36396	Owl.prototype.refresh = function() {
36397		this.enter('refreshing');
36398		this.trigger('refresh');
36399
36400		this.setup();
36401
36402		this.optionsLogic();
36403
36404		this.$element.addClass(this.options.refreshClass);
36405
36406		this.update();
36407
36408		this.$element.removeClass(this.options.refreshClass);
36409
36410		this.leave('refreshing');
36411		this.trigger('refreshed');
36412	};
36413
36414	/**
36415	 * Checks window `resize` event.
36416	 * @protected
36417	 */
36418	Owl.prototype.onThrottledResize = function() {
36419		window.clearTimeout(this.resizeTimer);
36420		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
36421	};
36422
36423	/**
36424	 * Checks window `resize` event.
36425	 * @protected
36426	 */
36427	Owl.prototype.onResize = function() {
36428		if (!this._items.length) {
36429			return false;
36430		}
36431
36432		if (this._width === this.$element.width()) {
36433			return false;
36434		}
36435
36436		if (!this.isVisible()) {
36437			return false;
36438		}
36439
36440		this.enter('resizing');
36441
36442		if (this.trigger('resize').isDefaultPrevented()) {
36443			this.leave('resizing');
36444			return false;
36445		}
36446
36447		this.invalidate('width');
36448
36449		this.refresh();
36450
36451		this.leave('resizing');
36452		this.trigger('resized');
36453	};
36454
36455	/**
36456	 * Registers event handlers.
36457	 * @todo Check `msPointerEnabled`
36458	 * @todo #261
36459	 * @protected
36460	 */
36461	Owl.prototype.registerEventHandlers = function() {
36462		if ($.support.transition) {
36463			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
36464		}
36465
36466		if (this.settings.responsive !== false) {
36467			this.on(window, 'resize', this._handlers.onThrottledResize);
36468		}
36469
36470		if (this.settings.mouseDrag) {
36471			this.$element.addClass(this.options.dragClass);
36472			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
36473			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
36474		}
36475
36476		if (this.settings.touchDrag){
36477			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
36478			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
36479		}
36480	};
36481
36482	/**
36483	 * Handles `touchstart` and `mousedown` events.
36484	 * @todo Horizontal swipe threshold as option
36485	 * @todo #261
36486	 * @protected
36487	 * @param {Event} event - The event arguments.
36488	 */
36489	Owl.prototype.onDragStart = function(event) {
36490		var stage = null;
36491
36492		if (event.which === 3) {
36493			return;
36494		}
36495
36496		if ($.support.transform) {
36497			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
36498			stage = {
36499				x: stage[stage.length === 16 ? 12 : 4],
36500				y: stage[stage.length === 16 ? 13 : 5]
36501			};
36502		} else {
36503			stage = this.$stage.position();
36504			stage = {
36505				x: this.settings.rtl ?
36506					stage.left + this.$stage.width() - this.width() + this.settings.margin :
36507					stage.left,
36508				y: stage.top
36509			};
36510		}
36511
36512		if (this.is('animating')) {
36513			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
36514			this.invalidate('position');
36515		}
36516
36517		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
36518
36519		this.speed(0);
36520
36521		this._drag.time = new Date().getTime();
36522		this._drag.target = $(event.target);
36523		this._drag.stage.start = stage;
36524		this._drag.stage.current = stage;
36525		this._drag.pointer = this.pointer(event);
36526
36527		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
36528
36529		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
36530			var delta = this.difference(this._drag.pointer, this.pointer(event));
36531
36532			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
36533
36534			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
36535				return;
36536			}
36537
36538			event.preventDefault();
36539
36540			this.enter('dragging');
36541			this.trigger('drag');
36542		}, this));
36543	};
36544
36545	/**
36546	 * Handles the `touchmove` and `mousemove` events.
36547	 * @todo #261
36548	 * @protected
36549	 * @param {Event} event - The event arguments.
36550	 */
36551	Owl.prototype.onDragMove = function(event) {
36552		var minimum = null,
36553			maximum = null,
36554			pull = null,
36555			delta = this.difference(this._drag.pointer, this.pointer(event)),
36556			stage = this.difference(this._drag.stage.start, delta);
36557
36558		if (!this.is('dragging')) {
36559			return;
36560		}
36561
36562		event.preventDefault();
36563
36564		if (this.settings.loop) {
36565			minimum = this.coordinates(this.minimum());
36566			maximum = this.coordinates(this.maximum() + 1) - minimum;
36567			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
36568		} else {
36569			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
36570			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
36571			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
36572			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
36573		}
36574
36575		this._drag.stage.current = stage;
36576
36577		this.animate(stage.x);
36578	};
36579
36580	/**
36581	 * Handles the `touchend` and `mouseup` events.
36582	 * @todo #261
36583	 * @todo Threshold for click event
36584	 * @protected
36585	 * @param {Event} event - The event arguments.
36586	 */
36587	Owl.prototype.onDragEnd = function(event) {
36588		var delta = this.difference(this._drag.pointer, this.pointer(event)),
36589			stage = this._drag.stage.current,
36590			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
36591
36592		$(document).off('.owl.core');
36593
36594		this.$element.removeClass(this.options.grabClass);
36595
36596		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
36597			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
36598			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
36599			this.invalidate('position');
36600			this.update();
36601
36602			this._drag.direction = direction;
36603
36604			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
36605				this._drag.target.one('click.owl.core', function() { return false; });
36606			}
36607		}
36608
36609		if (!this.is('dragging')) {
36610			return;
36611		}
36612
36613		this.leave('dragging');
36614		this.trigger('dragged');
36615	};
36616
36617	/**
36618	 * Gets absolute position of the closest item for a coordinate.
36619	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
36620	 * @protected
36621	 * @param {Number} coordinate - The coordinate in pixel.
36622	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
36623	 * @return {Number} - The absolute position of the closest item.
36624	 */
36625	Owl.prototype.closest = function(coordinate, direction) {
36626		var position = -1,
36627			pull = 30,
36628			width = this.width(),
36629			coordinates = this.coordinates();
36630
36631		if (!this.settings.freeDrag) {
36632			// check closest item
36633			$.each(coordinates, $.proxy(function(index, value) {
36634				// on a left pull, check on current index
36635				if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
36636					position = index;
36637				// on a right pull, check on previous index
36638				// to do so, subtract width from value and set position = index + 1
36639				} else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) {
36640					position = index + 1;
36641				} else if (this.op(coordinate, '<', value)
36642					&& this.op(coordinate, '>', coordinates[index + 1] !== undefined ? coordinates[index + 1] : value - width)) {
36643					position = direction === 'left' ? index + 1 : index;
36644				}
36645				return position === -1;
36646			}, this));
36647		}
36648
36649		if (!this.settings.loop) {
36650			// non loop boundries
36651			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
36652				position = coordinate = this.minimum();
36653			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
36654				position = coordinate = this.maximum();
36655			}
36656		}
36657
36658		return position;
36659	};
36660
36661	/**
36662	 * Animates the stage.
36663	 * @todo #270
36664	 * @public
36665	 * @param {Number} coordinate - The coordinate in pixels.
36666	 */
36667	Owl.prototype.animate = function(coordinate) {
36668		var animate = this.speed() > 0;
36669
36670		this.is('animating') && this.onTransitionEnd();
36671
36672		if (animate) {
36673			this.enter('animating');
36674			this.trigger('translate');
36675		}
36676
36677		if ($.support.transform3d && $.support.transition) {
36678			this.$stage.css({
36679				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
36680				transition: (this.speed() / 1000) + 's' + (
36681					this.settings.slideTransition ? ' ' + this.settings.slideTransition : ''
36682				)
36683			});
36684		} else if (animate) {
36685			this.$stage.animate({
36686				left: coordinate + 'px'
36687			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
36688		} else {
36689			this.$stage.css({
36690				left: coordinate + 'px'
36691			});
36692		}
36693	};
36694
36695	/**
36696	 * Checks whether the carousel is in a specific state or not.
36697	 * @param {String} state - The state to check.
36698	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
36699	 */
36700	Owl.prototype.is = function(state) {
36701		return this._states.current[state] && this._states.current[state] > 0;
36702	};
36703
36704	/**
36705	 * Sets the absolute position of the current item.
36706	 * @public
36707	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
36708	 * @returns {Number} - The absolute position of the current item.
36709	 */
36710	Owl.prototype.current = function(position) {
36711		if (position === undefined) {
36712			return this._current;
36713		}
36714
36715		if (this._items.length === 0) {
36716			return undefined;
36717		}
36718
36719		position = this.normalize(position);
36720
36721		if (this._current !== position) {
36722			var event = this.trigger('change', { property: { name: 'position', value: position } });
36723
36724			if (event.data !== undefined) {
36725				position = this.normalize(event.data);
36726			}
36727
36728			this._current = position;
36729
36730			this.invalidate('position');
36731
36732			this.trigger('changed', { property: { name: 'position', value: this._current } });
36733		}
36734
36735		return this._current;
36736	};
36737
36738	/**
36739	 * Invalidates the given part of the update routine.
36740	 * @param {String} [part] - The part to invalidate.
36741	 * @returns {Array.<String>} - The invalidated parts.
36742	 */
36743	Owl.prototype.invalidate = function(part) {
36744		if ($.type(part) === 'string') {
36745			this._invalidated[part] = true;
36746			this.is('valid') && this.leave('valid');
36747		}
36748		return $.map(this._invalidated, function(v, i) { return i });
36749	};
36750
36751	/**
36752	 * Resets the absolute position of the current item.
36753	 * @public
36754	 * @param {Number} position - The absolute position of the new item.
36755	 */
36756	Owl.prototype.reset = function(position) {
36757		position = this.normalize(position);
36758
36759		if (position === undefined) {
36760			return;
36761		}
36762
36763		this._speed = 0;
36764		this._current = position;
36765
36766		this.suppress([ 'translate', 'translated' ]);
36767
36768		this.animate(this.coordinates(position));
36769
36770		this.release([ 'translate', 'translated' ]);
36771	};
36772
36773	/**
36774	 * Normalizes an absolute or a relative position of an item.
36775	 * @public
36776	 * @param {Number} position - The absolute or relative position to normalize.
36777	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
36778	 * @returns {Number} - The normalized position.
36779	 */
36780	Owl.prototype.normalize = function(position, relative) {
36781		var n = this._items.length,
36782			m = relative ? 0 : this._clones.length;
36783
36784		if (!this.isNumeric(position) || n < 1) {
36785			position = undefined;
36786		} else if (position < 0 || position >= n + m) {
36787			position = ((position - m / 2) % n + n) % n + m / 2;
36788		}
36789
36790		return position;
36791	};
36792
36793	/**
36794	 * Converts an absolute position of an item into a relative one.
36795	 * @public
36796	 * @param {Number} position - The absolute position to convert.
36797	 * @returns {Number} - The converted position.
36798	 */
36799	Owl.prototype.relative = function(position) {
36800		position -= this._clones.length / 2;
36801		return this.normalize(position, true);
36802	};
36803
36804	/**
36805	 * Gets the maximum position for the current item.
36806	 * @public
36807	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
36808	 * @returns {Number}
36809	 */
36810	Owl.prototype.maximum = function(relative) {
36811		var settings = this.settings,
36812			maximum = this._coordinates.length,
36813			iterator,
36814			reciprocalItemsWidth,
36815			elementWidth;
36816
36817		if (settings.loop) {
36818			maximum = this._clones.length / 2 + this._items.length - 1;
36819		} else if (settings.autoWidth || settings.merge) {
36820			iterator = this._items.length;
36821			if (iterator) {
36822				reciprocalItemsWidth = this._items[--iterator].width();
36823				elementWidth = this.$element.width();
36824				while (iterator--) {
36825					reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin;
36826					if (reciprocalItemsWidth > elementWidth) {
36827						break;
36828					}
36829				}
36830			}
36831			maximum = iterator + 1;
36832		} else if (settings.center) {
36833			maximum = this._items.length - 1;
36834		} else {
36835			maximum = this._items.length - settings.items;
36836		}
36837
36838		if (relative) {
36839			maximum -= this._clones.length / 2;
36840		}
36841
36842		return Math.max(maximum, 0);
36843	};
36844
36845	/**
36846	 * Gets the minimum position for the current item.
36847	 * @public
36848	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
36849	 * @returns {Number}
36850	 */
36851	Owl.prototype.minimum = function(relative) {
36852		return relative ? 0 : this._clones.length / 2;
36853	};
36854
36855	/**
36856	 * Gets an item at the specified relative position.
36857	 * @public
36858	 * @param {Number} [position] - The relative position of the item.
36859	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
36860	 */
36861	Owl.prototype.items = function(position) {
36862		if (position === undefined) {
36863			return this._items.slice();
36864		}
36865
36866		position = this.normalize(position, true);
36867		return this._items[position];
36868	};
36869
36870	/**
36871	 * Gets an item at the specified relative position.
36872	 * @public
36873	 * @param {Number} [position] - The relative position of the item.
36874	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
36875	 */
36876	Owl.prototype.mergers = function(position) {
36877		if (position === undefined) {
36878			return this._mergers.slice();
36879		}
36880
36881		position = this.normalize(position, true);
36882		return this._mergers[position];
36883	};
36884
36885	/**
36886	 * Gets the absolute positions of clones for an item.
36887	 * @public
36888	 * @param {Number} [position] - The relative position of the item.
36889	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
36890	 */
36891	Owl.prototype.clones = function(position) {
36892		var odd = this._clones.length / 2,
36893			even = odd + this._items.length,
36894			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
36895
36896		if (position === undefined) {
36897			return $.map(this._clones, function(v, i) { return map(i) });
36898		}
36899
36900		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
36901	};
36902
36903	/**
36904	 * Sets the current animation speed.
36905	 * @public
36906	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
36907	 * @returns {Number} - The current animation speed in milliseconds.
36908	 */
36909	Owl.prototype.speed = function(speed) {
36910		if (speed !== undefined) {
36911			this._speed = speed;
36912		}
36913
36914		return this._speed;
36915	};
36916
36917	/**
36918	 * Gets the coordinate of an item.
36919	 * @todo The name of this method is missleanding.
36920	 * @public
36921	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
36922	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
36923	 */
36924	Owl.prototype.coordinates = function(position) {
36925		var multiplier = 1,
36926			newPosition = position - 1,
36927			coordinate;
36928
36929		if (position === undefined) {
36930			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
36931				return this.coordinates(index);
36932			}, this));
36933		}
36934
36935		if (this.settings.center) {
36936			if (this.settings.rtl) {
36937				multiplier = -1;
36938				newPosition = position + 1;
36939			}
36940
36941			coordinate = this._coordinates[position];
36942			coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
36943		} else {
36944			coordinate = this._coordinates[newPosition] || 0;
36945		}
36946
36947		coordinate = Math.ceil(coordinate);
36948
36949		return coordinate;
36950	};
36951
36952	/**
36953	 * Calculates the speed for a translation.
36954	 * @protected
36955	 * @param {Number} from - The absolute position of the start item.
36956	 * @param {Number} to - The absolute position of the target item.
36957	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
36958	 * @returns {Number} - The time in milliseconds for the translation.
36959	 */
36960	Owl.prototype.duration = function(from, to, factor) {
36961		if (factor === 0) {
36962			return 0;
36963		}
36964
36965		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
36966	};
36967
36968	/**
36969	 * Slides to the specified item.
36970	 * @public
36971	 * @param {Number} position - The position of the item.
36972	 * @param {Number} [speed] - The time in milliseconds for the transition.
36973	 */
36974	Owl.prototype.to = function(position, speed) {
36975		var current = this.current(),
36976			revert = null,
36977			distance = position - this.relative(current),
36978			direction = (distance > 0) - (distance < 0),
36979			items = this._items.length,
36980			minimum = this.minimum(),
36981			maximum = this.maximum();
36982
36983		if (this.settings.loop) {
36984			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
36985				distance += direction * -1 * items;
36986			}
36987
36988			position = current + distance;
36989			revert = ((position - minimum) % items + items) % items + minimum;
36990
36991			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
36992				current = revert - distance;
36993				position = revert;
36994				this.reset(current);
36995			}
36996		} else if (this.settings.rewind) {
36997			maximum += 1;
36998			position = (position % maximum + maximum) % maximum;
36999		} else {
37000			position = Math.max(minimum, Math.min(maximum, position));
37001		}
37002
37003		this.speed(this.duration(current, position, speed));
37004		this.current(position);
37005
37006		if (this.isVisible()) {
37007			this.update();
37008		}
37009	};
37010
37011	/**
37012	 * Slides to the next item.
37013	 * @public
37014	 * @param {Number} [speed] - The time in milliseconds for the transition.
37015	 */
37016	Owl.prototype.next = function(speed) {
37017		speed = speed || false;
37018		this.to(this.relative(this.current()) + 1, speed);
37019	};
37020
37021	/**
37022	 * Slides to the previous item.
37023	 * @public
37024	 * @param {Number} [speed] - The time in milliseconds for the transition.
37025	 */
37026	Owl.prototype.prev = function(speed) {
37027		speed = speed || false;
37028		this.to(this.relative(this.current()) - 1, speed);
37029	};
37030
37031	/**
37032	 * Handles the end of an animation.
37033	 * @protected
37034	 * @param {Event} event - The event arguments.
37035	 */
37036	Owl.prototype.onTransitionEnd = function(event) {
37037
37038		// if css2 animation then event object is undefined
37039		if (event !== undefined) {
37040			event.stopPropagation();
37041
37042			// Catch only owl-stage transitionEnd event
37043			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
37044				return false;
37045			}
37046		}
37047
37048		this.leave('animating');
37049		this.trigger('translated');
37050	};
37051
37052	/**
37053	 * Gets viewport width.
37054	 * @protected
37055	 * @return {Number} - The width in pixel.
37056	 */
37057	Owl.prototype.viewport = function() {
37058		var width;
37059		if (this.options.responsiveBaseElement !== window) {
37060			width = $(this.options.responsiveBaseElement).width();
37061		} else if (window.innerWidth) {
37062			width = window.innerWidth;
37063		} else if (document.documentElement && document.documentElement.clientWidth) {
37064			width = document.documentElement.clientWidth;
37065		} else {
37066			console.warn('Can not detect viewport width.');
37067		}
37068		return width;
37069	};
37070
37071	/**
37072	 * Replaces the current content.
37073	 * @public
37074	 * @param {HTMLElement|jQuery|String} content - The new content.
37075	 */
37076	Owl.prototype.replace = function(content) {
37077		this.$stage.empty();
37078		this._items = [];
37079
37080		if (content) {
37081			content = (content instanceof jQuery) ? content : $(content);
37082		}
37083
37084		if (this.settings.nestedItemSelector) {
37085			content = content.find('.' + this.settings.nestedItemSelector);
37086		}
37087
37088		content.filter(function() {
37089			return this.nodeType === 1;
37090		}).each($.proxy(function(index, item) {
37091			item = this.prepare(item);
37092			this.$stage.append(item);
37093			this._items.push(item);
37094			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
37095		}, this));
37096
37097		this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
37098
37099		this.invalidate('items');
37100	};
37101
37102	/**
37103	 * Adds an item.
37104	 * @todo Use `item` instead of `content` for the event arguments.
37105	 * @public
37106	 * @param {HTMLElement|jQuery|String} content - The item content to add.
37107	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
37108	 */
37109	Owl.prototype.add = function(content, position) {
37110		var current = this.relative(this._current);
37111
37112		position = position === undefined ? this._items.length : this.normalize(position, true);
37113		content = content instanceof jQuery ? content : $(content);
37114
37115		this.trigger('add', { content: content, position: position });
37116
37117		content = this.prepare(content);
37118
37119		if (this._items.length === 0 || position === this._items.length) {
37120			this._items.length === 0 && this.$stage.append(content);
37121			this._items.length !== 0 && this._items[position - 1].after(content);
37122			this._items.push(content);
37123			this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
37124		} else {
37125			this._items[position].before(content);
37126			this._items.splice(position, 0, content);
37127			this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
37128		}
37129
37130		this._items[current] && this.reset(this._items[current].index());
37131
37132		this.invalidate('items');
37133
37134		this.trigger('added', { content: content, position: position });
37135	};
37136
37137	/**
37138	 * Removes an item by its position.
37139	 * @todo Use `item` instead of `content` for the event arguments.
37140	 * @public
37141	 * @param {Number} position - The relative position of the item to remove.
37142	 */
37143	Owl.prototype.remove = function(position) {
37144		position = this.normalize(position, true);
37145
37146		if (position === undefined) {
37147			return;
37148		}
37149
37150		this.trigger('remove', { content: this._items[position], position: position });
37151
37152		this._items[position].remove();
37153		this._items.splice(position, 1);
37154		this._mergers.splice(position, 1);
37155
37156		this.invalidate('items');
37157
37158		this.trigger('removed', { content: null, position: position });
37159	};
37160
37161	/**
37162	 * Preloads images with auto width.
37163	 * @todo Replace by a more generic approach
37164	 * @protected
37165	 */
37166	Owl.prototype.preloadAutoWidthImages = function(images) {
37167		images.each($.proxy(function(i, element) {
37168			this.enter('pre-loading');
37169			element = $(element);
37170			$(new Image()).one('load', $.proxy(function(e) {
37171				element.attr('src', e.target.src);
37172				element.css('opacity', 1);
37173				this.leave('pre-loading');
37174				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
37175			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
37176		}, this));
37177	};
37178
37179	/**
37180	 * Destroys the carousel.
37181	 * @public
37182	 */
37183	Owl.prototype.destroy = function() {
37184
37185		this.$element.off('.owl.core');
37186		this.$stage.off('.owl.core');
37187		$(document).off('.owl.core');
37188
37189		if (this.settings.responsive !== false) {
37190			window.clearTimeout(this.resizeTimer);
37191			this.off(window, 'resize', this._handlers.onThrottledResize);
37192		}
37193
37194		for (var i in this._plugins) {
37195			this._plugins[i].destroy();
37196		}
37197
37198		this.$stage.children('.cloned').remove();
37199
37200		this.$stage.unwrap();
37201		this.$stage.children().contents().unwrap();
37202		this.$stage.children().unwrap();
37203		this.$stage.remove();
37204		this.$element
37205			.removeClass(this.options.refreshClass)
37206			.removeClass(this.options.loadingClass)
37207			.removeClass(this.options.loadedClass)
37208			.removeClass(this.options.rtlClass)
37209			.removeClass(this.options.dragClass)
37210			.removeClass(this.options.grabClass)
37211			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
37212			.removeData('owl.carousel');
37213	};
37214
37215	/**
37216	 * Operators to calculate right-to-left and left-to-right.
37217	 * @protected
37218	 * @param {Number} [a] - The left side operand.
37219	 * @param {String} [o] - The operator.
37220	 * @param {Number} [b] - The right side operand.
37221	 */
37222	Owl.prototype.op = function(a, o, b) {
37223		var rtl = this.settings.rtl;
37224		switch (o) {
37225			case '<':
37226				return rtl ? a > b : a < b;
37227			case '>':
37228				return rtl ? a < b : a > b;
37229			case '>=':
37230				return rtl ? a <= b : a >= b;
37231			case '<=':
37232				return rtl ? a >= b : a <= b;
37233			default:
37234				break;
37235		}
37236	};
37237
37238	/**
37239	 * Attaches to an internal event.
37240	 * @protected
37241	 * @param {HTMLElement} element - The event source.
37242	 * @param {String} event - The event name.
37243	 * @param {Function} listener - The event handler to attach.
37244	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
37245	 */
37246	Owl.prototype.on = function(element, event, listener, capture) {
37247		if (element.addEventListener) {
37248			element.addEventListener(event, listener, capture);
37249		} else if (element.attachEvent) {
37250			element.attachEvent('on' + event, listener);
37251		}
37252	};
37253
37254	/**
37255	 * Detaches from an internal event.
37256	 * @protected
37257	 * @param {HTMLElement} element - The event source.
37258	 * @param {String} event - The event name.
37259	 * @param {Function} listener - The attached event handler to detach.
37260	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
37261	 */
37262	Owl.prototype.off = function(element, event, listener, capture) {
37263		if (element.removeEventListener) {
37264			element.removeEventListener(event, listener, capture);
37265		} else if (element.detachEvent) {
37266			element.detachEvent('on' + event, listener);
37267		}
37268	};
37269
37270	/**
37271	 * Triggers a public event.
37272	 * @todo Remove `status`, `relatedTarget` should be used instead.
37273	 * @protected
37274	 * @param {String} name - The event name.
37275	 * @param {*} [data=null] - The event data.
37276	 * @param {String} [namespace=carousel] - The event namespace.
37277	 * @param {String} [state] - The state which is associated with the event.
37278	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
37279	 * @returns {Event} - The event arguments.
37280	 */
37281	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
37282		var status = {
37283			item: { count: this._items.length, index: this.current() }
37284		}, handler = $.camelCase(
37285			$.grep([ 'on', name, namespace ], function(v) { return v })
37286				.join('-').toLowerCase()
37287		), event = $.Event(
37288			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
37289			$.extend({ relatedTarget: this }, status, data)
37290		);
37291
37292		if (!this._supress[name]) {
37293			$.each(this._plugins, function(name, plugin) {
37294				if (plugin.onTrigger) {
37295					plugin.onTrigger(event);
37296				}
37297			});
37298
37299			this.register({ type: Owl.Type.Event, name: name });
37300			this.$element.trigger(event);
37301
37302			if (this.settings && typeof this.settings[handler] === 'function') {
37303				this.settings[handler].call(this, event);
37304			}
37305		}
37306
37307		return event;
37308	};
37309
37310	/**
37311	 * Enters a state.
37312	 * @param name - The state name.
37313	 */
37314	Owl.prototype.enter = function(name) {
37315		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
37316			if (this._states.current[name] === undefined) {
37317				this._states.current[name] = 0;
37318			}
37319
37320			this._states.current[name]++;
37321		}, this));
37322	};
37323
37324	/**
37325	 * Leaves a state.
37326	 * @param name - The state name.
37327	 */
37328	Owl.prototype.leave = function(name) {
37329		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
37330			this._states.current[name]--;
37331		}, this));
37332	};
37333
37334	/**
37335	 * Registers an event or state.
37336	 * @public
37337	 * @param {Object} object - The event or state to register.
37338	 */
37339	Owl.prototype.register = function(object) {
37340		if (object.type === Owl.Type.Event) {
37341			if (!$.event.special[object.name]) {
37342				$.event.special[object.name] = {};
37343			}
37344
37345			if (!$.event.special[object.name].owl) {
37346				var _default = $.event.special[object.name]._default;
37347				$.event.special[object.name]._default = function(e) {
37348					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
37349						return _default.apply(this, arguments);
37350					}
37351					return e.namespace && e.namespace.indexOf('owl') > -1;
37352				};
37353				$.event.special[object.name].owl = true;
37354			}
37355		} else if (object.type === Owl.Type.State) {
37356			if (!this._states.tags[object.name]) {
37357				this._states.tags[object.name] = object.tags;
37358			} else {
37359				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
37360			}
37361
37362			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
37363				return $.inArray(tag, this._states.tags[object.name]) === i;
37364			}, this));
37365		}
37366	};
37367
37368	/**
37369	 * Suppresses events.
37370	 * @protected
37371	 * @param {Array.<String>} events - The events to suppress.
37372	 */
37373	Owl.prototype.suppress = function(events) {
37374		$.each(events, $.proxy(function(index, event) {
37375			this._supress[event] = true;
37376		}, this));
37377	};
37378
37379	/**
37380	 * Releases suppressed events.
37381	 * @protected
37382	 * @param {Array.<String>} events - The events to release.
37383	 */
37384	Owl.prototype.release = function(events) {
37385		$.each(events, $.proxy(function(index, event) {
37386			delete this._supress[event];
37387		}, this));
37388	};
37389
37390	/**
37391	 * Gets unified pointer coordinates from event.
37392	 * @todo #261
37393	 * @protected
37394	 * @param {Event} - The `mousedown` or `touchstart` event.
37395	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
37396	 */
37397	Owl.prototype.pointer = function(event) {
37398		var result = { x: null, y: null };
37399
37400		event = event.originalEvent || event || window.event;
37401
37402		event = event.touches && event.touches.length ?
37403			event.touches[0] : event.changedTouches && event.changedTouches.length ?
37404				event.changedTouches[0] : event;
37405
37406		if (event.pageX) {
37407			result.x = event.pageX;
37408			result.y = event.pageY;
37409		} else {
37410			result.x = event.clientX;
37411			result.y = event.clientY;
37412		}
37413
37414		return result;
37415	};
37416
37417	/**
37418	 * Determines if the input is a Number or something that can be coerced to a Number
37419	 * @protected
37420	 * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
37421	 * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
37422	 */
37423	Owl.prototype.isNumeric = function(number) {
37424		return !isNaN(parseFloat(number));
37425	};
37426
37427	/**
37428	 * Gets the difference of two vectors.
37429	 * @todo #261
37430	 * @protected
37431	 * @param {Object} - The first vector.
37432	 * @param {Object} - The second vector.
37433	 * @returns {Object} - The difference.
37434	 */
37435	Owl.prototype.difference = function(first, second) {
37436		return {
37437			x: first.x - second.x,
37438			y: first.y - second.y
37439		};
37440	};
37441
37442	/**
37443	 * The jQuery Plugin for the Owl Carousel
37444	 * @todo Navigation plugin `next` and `prev`
37445	 * @public
37446	 */
37447	$.fn.owlCarousel = function(option) {
37448		var args = Array.prototype.slice.call(arguments, 1);
37449
37450		return this.each(function() {
37451			var $this = $(this),
37452				data = $this.data('owl.carousel');
37453
37454			if (!data) {
37455				data = new Owl(this, typeof option == 'object' && option);
37456				$this.data('owl.carousel', data);
37457
37458				$.each([
37459					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
37460				], function(i, event) {
37461					data.register({ type: Owl.Type.Event, name: event });
37462					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
37463						if (e.namespace && e.relatedTarget !== this) {
37464							this.suppress([ event ]);
37465							data[event].apply(this, [].slice.call(arguments, 1));
37466							this.release([ event ]);
37467						}
37468					}, data));
37469				});
37470			}
37471
37472			if (typeof option == 'string' && option.charAt(0) !== '_') {
37473				data[option].apply(data, args);
37474			}
37475		});
37476	};
37477
37478	/**
37479	 * The constructor for the jQuery Plugin
37480	 * @public
37481	 */
37482	$.fn.owlCarousel.Constructor = Owl;
37483
37484})(window.Zepto || window.jQuery, window, document);
37485
37486/**
37487 * AutoRefresh Plugin
37488 * @version 2.3.4
37489 * @author Artus Kolanowski
37490 * @author David Deutsch
37491 * @license The MIT License (MIT)
37492 */
37493;(function($, window, document, undefined) {
37494
37495	/**
37496	 * Creates the auto refresh plugin.
37497	 * @class The Auto Refresh Plugin
37498	 * @param {Owl} carousel - The Owl Carousel
37499	 */
37500	var AutoRefresh = function(carousel) {
37501		/**
37502		 * Reference to the core.
37503		 * @protected
37504		 * @type {Owl}
37505		 */
37506		this._core = carousel;
37507
37508		/**
37509		 * Refresh interval.
37510		 * @protected
37511		 * @type {number}
37512		 */
37513		this._interval = null;
37514
37515		/**
37516		 * Whether the element is currently visible or not.
37517		 * @protected
37518		 * @type {Boolean}
37519		 */
37520		this._visible = null;
37521
37522		/**
37523		 * All event handlers.
37524		 * @protected
37525		 * @type {Object}
37526		 */
37527		this._handlers = {
37528			'initialized.owl.carousel': $.proxy(function(e) {
37529				if (e.namespace && this._core.settings.autoRefresh) {
37530					this.watch();
37531				}
37532			}, this)
37533		};
37534
37535		// set default options
37536		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
37537
37538		// register event handlers
37539		this._core.$element.on(this._handlers);
37540	};
37541
37542	/**
37543	 * Default options.
37544	 * @public
37545	 */
37546	AutoRefresh.Defaults = {
37547		autoRefresh: true,
37548		autoRefreshInterval: 500
37549	};
37550
37551	/**
37552	 * Watches the element.
37553	 */
37554	AutoRefresh.prototype.watch = function() {
37555		if (this._interval) {
37556			return;
37557		}
37558
37559		this._visible = this._core.isVisible();
37560		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
37561	};
37562
37563	/**
37564	 * Refreshes the element.
37565	 */
37566	AutoRefresh.prototype.refresh = function() {
37567		if (this._core.isVisible() === this._visible) {
37568			return;
37569		}
37570
37571		this._visible = !this._visible;
37572
37573		this._core.$element.toggleClass('owl-hidden', !this._visible);
37574
37575		this._visible && (this._core.invalidate('width') && this._core.refresh());
37576	};
37577
37578	/**
37579	 * Destroys the plugin.
37580	 */
37581	AutoRefresh.prototype.destroy = function() {
37582		var handler, property;
37583
37584		window.clearInterval(this._interval);
37585
37586		for (handler in this._handlers) {
37587			this._core.$element.off(handler, this._handlers[handler]);
37588		}
37589		for (property in Object.getOwnPropertyNames(this)) {
37590			typeof this[property] != 'function' && (this[property] = null);
37591		}
37592	};
37593
37594	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
37595
37596})(window.Zepto || window.jQuery, window, document);
37597
37598/**
37599 * Lazy Plugin
37600 * @version 2.3.4
37601 * @author Bartosz Wojciechowski
37602 * @author David Deutsch
37603 * @license The MIT License (MIT)
37604 */
37605;(function($, window, document, undefined) {
37606
37607	/**
37608	 * Creates the lazy plugin.
37609	 * @class The Lazy Plugin
37610	 * @param {Owl} carousel - The Owl Carousel
37611	 */
37612	var Lazy = function(carousel) {
37613
37614		/**
37615		 * Reference to the core.
37616		 * @protected
37617		 * @type {Owl}
37618		 */
37619		this._core = carousel;
37620
37621		/**
37622		 * Already loaded items.
37623		 * @protected
37624		 * @type {Array.<jQuery>}
37625		 */
37626		this._loaded = [];
37627
37628		/**
37629		 * Event handlers.
37630		 * @protected
37631		 * @type {Object}
37632		 */
37633		this._handlers = {
37634			'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) {
37635				if (!e.namespace) {
37636					return;
37637				}
37638
37639				if (!this._core.settings || !this._core.settings.lazyLoad) {
37640					return;
37641				}
37642
37643				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
37644					var settings = this._core.settings,
37645						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
37646						i = ((settings.center && n * -1) || 0),
37647						position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i,
37648						clones = this._core.clones().length,
37649						load = $.proxy(function(i, v) { this.load(v) }, this);
37650					//TODO: Need documentation for this new option
37651					if (settings.lazyLoadEager > 0) {
37652						n += settings.lazyLoadEager;
37653						// If the carousel is looping also preload images that are to the "left"
37654						if (settings.loop) {
37655              position -= settings.lazyLoadEager;
37656              n++;
37657            }
37658					}
37659
37660					while (i++ < n) {
37661						this.load(clones / 2 + this._core.relative(position));
37662						clones && $.each(this._core.clones(this._core.relative(position)), load);
37663						position++;
37664					}
37665				}
37666			}, this)
37667		};
37668
37669		// set the default options
37670		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
37671
37672		// register event handler
37673		this._core.$element.on(this._handlers);
37674	};
37675
37676	/**
37677	 * Default options.
37678	 * @public
37679	 */
37680	Lazy.Defaults = {
37681		lazyLoad: false,
37682		lazyLoadEager: 0
37683	};
37684
37685	/**
37686	 * Loads all resources of an item at the specified position.
37687	 * @param {Number} position - The absolute position of the item.
37688	 * @protected
37689	 */
37690	Lazy.prototype.load = function(position) {
37691		var $item = this._core.$stage.children().eq(position),
37692			$elements = $item && $item.find('.owl-lazy');
37693
37694		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
37695			return;
37696		}
37697
37698		$elements.each($.proxy(function(index, element) {
37699			var $element = $(element), image,
37700                url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src') || $element.attr('data-srcset');
37701
37702			this._core.trigger('load', { element: $element, url: url }, 'lazy');
37703
37704			if ($element.is('img')) {
37705				$element.one('load.owl.lazy', $.proxy(function() {
37706					$element.css('opacity', 1);
37707					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
37708				}, this)).attr('src', url);
37709            } else if ($element.is('source')) {
37710                $element.one('load.owl.lazy', $.proxy(function() {
37711                    this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
37712                }, this)).attr('srcset', url);
37713			} else {
37714				image = new Image();
37715				image.onload = $.proxy(function() {
37716					$element.css({
37717						'background-image': 'url("' + url + '")',
37718						'opacity': '1'
37719					});
37720					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
37721				}, this);
37722				image.src = url;
37723			}
37724		}, this));
37725
37726		this._loaded.push($item.get(0));
37727	};
37728
37729	/**
37730	 * Destroys the plugin.
37731	 * @public
37732	 */
37733	Lazy.prototype.destroy = function() {
37734		var handler, property;
37735
37736		for (handler in this.handlers) {
37737			this._core.$element.off(handler, this.handlers[handler]);
37738		}
37739		for (property in Object.getOwnPropertyNames(this)) {
37740			typeof this[property] != 'function' && (this[property] = null);
37741		}
37742	};
37743
37744	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
37745
37746})(window.Zepto || window.jQuery, window, document);
37747
37748/**
37749 * AutoHeight Plugin
37750 * @version 2.3.4
37751 * @author Bartosz Wojciechowski
37752 * @author David Deutsch
37753 * @license The MIT License (MIT)
37754 */
37755;(function($, window, document, undefined) {
37756
37757	/**
37758	 * Creates the auto height plugin.
37759	 * @class The Auto Height Plugin
37760	 * @param {Owl} carousel - The Owl Carousel
37761	 */
37762	var AutoHeight = function(carousel) {
37763		/**
37764		 * Reference to the core.
37765		 * @protected
37766		 * @type {Owl}
37767		 */
37768		this._core = carousel;
37769
37770		this._previousHeight = null;
37771
37772		/**
37773		 * All event handlers.
37774		 * @protected
37775		 * @type {Object}
37776		 */
37777		this._handlers = {
37778			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
37779				if (e.namespace && this._core.settings.autoHeight) {
37780					this.update();
37781				}
37782			}, this),
37783			'changed.owl.carousel': $.proxy(function(e) {
37784				if (e.namespace && this._core.settings.autoHeight && e.property.name === 'position'){
37785					this.update();
37786				}
37787			}, this),
37788			'loaded.owl.lazy': $.proxy(function(e) {
37789				if (e.namespace && this._core.settings.autoHeight
37790					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
37791					this.update();
37792				}
37793			}, this)
37794		};
37795
37796		// set default options
37797		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
37798
37799		// register event handlers
37800		this._core.$element.on(this._handlers);
37801		this._intervalId = null;
37802		var refThis = this;
37803
37804		// These changes have been taken from a PR by gavrochelegnou proposed in #1575
37805		// and have been made compatible with the latest jQuery version
37806		$(window).on('load', function() {
37807			if (refThis._core.settings.autoHeight) {
37808				refThis.update();
37809			}
37810		});
37811
37812		// Autoresize the height of the carousel when window is resized
37813		// When carousel has images, the height is dependent on the width
37814		// and should also change on resize
37815		$(window).resize(function() {
37816			if (refThis._core.settings.autoHeight) {
37817				if (refThis._intervalId != null) {
37818					clearTimeout(refThis._intervalId);
37819				}
37820
37821				refThis._intervalId = setTimeout(function() {
37822					refThis.update();
37823				}, 250);
37824			}
37825		});
37826
37827	};
37828
37829	/**
37830	 * Default options.
37831	 * @public
37832	 */
37833	AutoHeight.Defaults = {
37834		autoHeight: false,
37835		autoHeightClass: 'owl-height'
37836	};
37837
37838	/**
37839	 * Updates the view.
37840	 */
37841	AutoHeight.prototype.update = function() {
37842		var start = this._core._current,
37843			end = start + this._core.settings.items,
37844			lazyLoadEnabled = this._core.settings.lazyLoad,
37845			visible = this._core.$stage.children().toArray().slice(start, end),
37846			heights = [],
37847			maxheight = 0;
37848
37849		$.each(visible, function(index, item) {
37850			heights.push($(item).height());
37851		});
37852
37853		maxheight = Math.max.apply(null, heights);
37854
37855		if (maxheight <= 1 && lazyLoadEnabled && this._previousHeight) {
37856			maxheight = this._previousHeight;
37857		}
37858
37859		this._previousHeight = maxheight;
37860
37861		this._core.$stage.parent()
37862			.height(maxheight)
37863			.addClass(this._core.settings.autoHeightClass);
37864	};
37865
37866	AutoHeight.prototype.destroy = function() {
37867		var handler, property;
37868
37869		for (handler in this._handlers) {
37870			this._core.$element.off(handler, this._handlers[handler]);
37871		}
37872		for (property in Object.getOwnPropertyNames(this)) {
37873			typeof this[property] !== 'function' && (this[property] = null);
37874		}
37875	};
37876
37877	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
37878
37879})(window.Zepto || window.jQuery, window, document);
37880
37881/**
37882 * Video Plugin
37883 * @version 2.3.4
37884 * @author Bartosz Wojciechowski
37885 * @author David Deutsch
37886 * @license The MIT License (MIT)
37887 */
37888;(function($, window, document, undefined) {
37889
37890	/**
37891	 * Creates the video plugin.
37892	 * @class The Video Plugin
37893	 * @param {Owl} carousel - The Owl Carousel
37894	 */
37895	var Video = function(carousel) {
37896		/**
37897		 * Reference to the core.
37898		 * @protected
37899		 * @type {Owl}
37900		 */
37901		this._core = carousel;
37902
37903		/**
37904		 * Cache all video URLs.
37905		 * @protected
37906		 * @type {Object}
37907		 */
37908		this._videos = {};
37909
37910		/**
37911		 * Current playing item.
37912		 * @protected
37913		 * @type {jQuery}
37914		 */
37915		this._playing = null;
37916
37917		/**
37918		 * All event handlers.
37919		 * @todo The cloned content removale is too late
37920		 * @protected
37921		 * @type {Object}
37922		 */
37923		this._handlers = {
37924			'initialized.owl.carousel': $.proxy(function(e) {
37925				if (e.namespace) {
37926					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
37927				}
37928			}, this),
37929			'resize.owl.carousel': $.proxy(function(e) {
37930				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
37931					e.preventDefault();
37932				}
37933			}, this),
37934			'refreshed.owl.carousel': $.proxy(function(e) {
37935				if (e.namespace && this._core.is('resizing')) {
37936					this._core.$stage.find('.cloned .owl-video-frame').remove();
37937				}
37938			}, this),
37939			'changed.owl.carousel': $.proxy(function(e) {
37940				if (e.namespace && e.property.name === 'position' && this._playing) {
37941					this.stop();
37942				}
37943			}, this),
37944			'prepared.owl.carousel': $.proxy(function(e) {
37945				if (!e.namespace) {
37946					return;
37947				}
37948
37949				var $element = $(e.content).find('.owl-video');
37950
37951				if ($element.length) {
37952					$element.css('display', 'none');
37953					this.fetch($element, $(e.content));
37954				}
37955			}, this)
37956		};
37957
37958		// set default options
37959		this._core.options = $.extend({}, Video.Defaults, this._core.options);
37960
37961		// register event handlers
37962		this._core.$element.on(this._handlers);
37963
37964		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
37965			this.play(e);
37966		}, this));
37967	};
37968
37969	/**
37970	 * Default options.
37971	 * @public
37972	 */
37973	Video.Defaults = {
37974		video: false,
37975		videoHeight: false,
37976		videoWidth: false
37977	};
37978
37979	/**
37980	 * Gets the video ID and the type (YouTube/Vimeo/vzaar only).
37981	 * @protected
37982	 * @param {jQuery} target - The target containing the video data.
37983	 * @param {jQuery} item - The item containing the video.
37984	 */
37985	Video.prototype.fetch = function(target, item) {
37986			var type = (function() {
37987					if (target.attr('data-vimeo-id')) {
37988						return 'vimeo';
37989					} else if (target.attr('data-vzaar-id')) {
37990						return 'vzaar'
37991					} else {
37992						return 'youtube';
37993					}
37994				})(),
37995				id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'),
37996				width = target.attr('data-width') || this._core.settings.videoWidth,
37997				height = target.attr('data-height') || this._core.settings.videoHeight,
37998				url = target.attr('href');
37999
38000		if (url) {
38001
38002			/*
38003					Parses the id's out of the following urls (and probably more):
38004					https://www.youtube.com/watch?v=:id
38005					https://youtu.be/:id
38006					https://vimeo.com/:id
38007					https://vimeo.com/channels/:channel/:id
38008					https://vimeo.com/groups/:group/videos/:id
38009					https://app.vzaar.com/videos/:id
38010
38011					Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F
38012			*/
38013
38014			id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com|be\-nocookie\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
38015
38016			if (id[3].indexOf('youtu') > -1) {
38017				type = 'youtube';
38018			} else if (id[3].indexOf('vimeo') > -1) {
38019				type = 'vimeo';
38020			} else if (id[3].indexOf('vzaar') > -1) {
38021				type = 'vzaar';
38022			} else {
38023				throw new Error('Video URL not supported.');
38024			}
38025			id = id[6];
38026		} else {
38027			throw new Error('Missing video URL.');
38028		}
38029
38030		this._videos[url] = {
38031			type: type,
38032			id: id,
38033			width: width,
38034			height: height
38035		};
38036
38037		item.attr('data-video', url);
38038
38039		this.thumbnail(target, this._videos[url]);
38040	};
38041
38042	/**
38043	 * Creates video thumbnail.
38044	 * @protected
38045	 * @param {jQuery} target - The target containing the video data.
38046	 * @param {Object} info - The video info object.
38047	 * @see `fetch`
38048	 */
38049	Video.prototype.thumbnail = function(target, video) {
38050		var tnLink,
38051			icon,
38052			path,
38053			dimensions = video.width && video.height ? 'width:' + video.width + 'px;height:' + video.height + 'px;' : '',
38054			customTn = target.find('img'),
38055			srcType = 'src',
38056			lazyClass = '',
38057			settings = this._core.settings,
38058			create = function(path) {
38059				icon = '<div class="owl-video-play-icon"></div>';
38060
38061				if (settings.lazyLoad) {
38062					tnLink = $('<div/>',{
38063						"class": 'owl-video-tn ' + lazyClass,
38064						"srcType": path
38065					});
38066				} else {
38067					tnLink = $( '<div/>', {
38068						"class": "owl-video-tn",
38069						"style": 'opacity:1;background-image:url(' + path + ')'
38070					});
38071				}
38072				target.after(tnLink);
38073				target.after(icon);
38074			};
38075
38076		// wrap video content into owl-video-wrapper div
38077		target.wrap( $( '<div/>', {
38078			"class": "owl-video-wrapper",
38079			"style": dimensions
38080		}));
38081
38082		if (this._core.settings.lazyLoad) {
38083			srcType = 'data-src';
38084			lazyClass = 'owl-lazy';
38085		}
38086
38087		// custom thumbnail
38088		if (customTn.length) {
38089			create(customTn.attr(srcType));
38090			customTn.remove();
38091			return false;
38092		}
38093
38094		if (video.type === 'youtube') {
38095			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
38096			create(path);
38097		} else if (video.type === 'vimeo') {
38098			$.ajax({
38099				type: 'GET',
38100				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
38101				jsonp: 'callback',
38102				dataType: 'jsonp',
38103				success: function(data) {
38104					path = data[0].thumbnail_large;
38105					create(path);
38106				}
38107			});
38108		} else if (video.type === 'vzaar') {
38109			$.ajax({
38110				type: 'GET',
38111				url: '//vzaar.com/api/videos/' + video.id + '.json',
38112				jsonp: 'callback',
38113				dataType: 'jsonp',
38114				success: function(data) {
38115					path = data.framegrab_url;
38116					create(path);
38117				}
38118			});
38119		}
38120	};
38121
38122	/**
38123	 * Stops the current video.
38124	 * @public
38125	 */
38126	Video.prototype.stop = function() {
38127		this._core.trigger('stop', null, 'video');
38128		this._playing.find('.owl-video-frame').remove();
38129		this._playing.removeClass('owl-video-playing');
38130		this._playing = null;
38131		this._core.leave('playing');
38132		this._core.trigger('stopped', null, 'video');
38133	};
38134
38135	/**
38136	 * Starts the current video.
38137	 * @public
38138	 * @param {Event} event - The event arguments.
38139	 */
38140	Video.prototype.play = function(event) {
38141		var target = $(event.target),
38142			item = target.closest('.' + this._core.settings.itemClass),
38143			video = this._videos[item.attr('data-video')],
38144			width = video.width || '100%',
38145			height = video.height || this._core.$stage.height(),
38146			html,
38147			iframe;
38148
38149		if (this._playing) {
38150			return;
38151		}
38152
38153		this._core.enter('playing');
38154		this._core.trigger('play', null, 'video');
38155
38156		item = this._core.items(this._core.relative(item.index()));
38157
38158		this._core.reset(item.index());
38159
38160		html = $( '<iframe frameborder="0" allowfullscreen mozallowfullscreen webkitAllowFullScreen ></iframe>' );
38161		html.attr( 'height', height );
38162		html.attr( 'width', width );
38163		if (video.type === 'youtube') {
38164			html.attr( 'src', '//www.youtube.com/embed/' + video.id + '?autoplay=1&rel=0&v=' + video.id );
38165		} else if (video.type === 'vimeo') {
38166			html.attr( 'src', '//player.vimeo.com/video/' + video.id + '?autoplay=1' );
38167		} else if (video.type === 'vzaar') {
38168			html.attr( 'src', '//view.vzaar.com/' + video.id + '/player?autoplay=true' );
38169		}
38170
38171		iframe = $(html).wrap( '<div class="owl-video-frame" />' ).insertAfter(item.find('.owl-video'));
38172
38173		this._playing = item.addClass('owl-video-playing');
38174	};
38175
38176	/**
38177	 * Checks whether an video is currently in full screen mode or not.
38178	 * @todo Bad style because looks like a readonly method but changes members.
38179	 * @protected
38180	 * @returns {Boolean}
38181	 */
38182	Video.prototype.isInFullScreen = function() {
38183		var element = document.fullscreenElement || document.mozFullScreenElement ||
38184				document.webkitFullscreenElement;
38185
38186		return element && $(element).parent().hasClass('owl-video-frame');
38187	};
38188
38189	/**
38190	 * Destroys the plugin.
38191	 */
38192	Video.prototype.destroy = function() {
38193		var handler, property;
38194
38195		this._core.$element.off('click.owl.video');
38196
38197		for (handler in this._handlers) {
38198			this._core.$element.off(handler, this._handlers[handler]);
38199		}
38200		for (property in Object.getOwnPropertyNames(this)) {
38201			typeof this[property] != 'function' && (this[property] = null);
38202		}
38203	};
38204
38205	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
38206
38207})(window.Zepto || window.jQuery, window, document);
38208
38209/**
38210 * Animate Plugin
38211 * @version 2.3.4
38212 * @author Bartosz Wojciechowski
38213 * @author David Deutsch
38214 * @license The MIT License (MIT)
38215 */
38216;(function($, window, document, undefined) {
38217
38218	/**
38219	 * Creates the animate plugin.
38220	 * @class The Navigation Plugin
38221	 * @param {Owl} scope - The Owl Carousel
38222	 */
38223	var Animate = function(scope) {
38224		this.core = scope;
38225		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
38226		this.swapping = true;
38227		this.previous = undefined;
38228		this.next = undefined;
38229
38230		this.handlers = {
38231			'change.owl.carousel': $.proxy(function(e) {
38232				if (e.namespace && e.property.name == 'position') {
38233					this.previous = this.core.current();
38234					this.next = e.property.value;
38235				}
38236			}, this),
38237			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
38238				if (e.namespace) {
38239					this.swapping = e.type == 'translated';
38240				}
38241			}, this),
38242			'translate.owl.carousel': $.proxy(function(e) {
38243				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
38244					this.swap();
38245				}
38246			}, this)
38247		};
38248
38249		this.core.$element.on(this.handlers);
38250	};
38251
38252	/**
38253	 * Default options.
38254	 * @public
38255	 */
38256	Animate.Defaults = {
38257		animateOut: false,
38258		animateIn: false
38259	};
38260
38261	/**
38262	 * Toggles the animation classes whenever an translations starts.
38263	 * @protected
38264	 * @returns {Boolean|undefined}
38265	 */
38266	Animate.prototype.swap = function() {
38267
38268		if (this.core.settings.items !== 1) {
38269			return;
38270		}
38271
38272		if (!$.support.animation || !$.support.transition) {
38273			return;
38274		}
38275
38276		this.core.speed(0);
38277
38278		var left,
38279			clear = $.proxy(this.clear, this),
38280			previous = this.core.$stage.children().eq(this.previous),
38281			next = this.core.$stage.children().eq(this.next),
38282			incoming = this.core.settings.animateIn,
38283			outgoing = this.core.settings.animateOut;
38284
38285		if (this.core.current() === this.previous) {
38286			return;
38287		}
38288
38289		if (outgoing) {
38290			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
38291			previous.one($.support.animation.end, clear)
38292				.css( { 'left': left + 'px' } )
38293				.addClass('animated owl-animated-out')
38294				.addClass(outgoing);
38295		}
38296
38297		if (incoming) {
38298			next.one($.support.animation.end, clear)
38299				.addClass('animated owl-animated-in')
38300				.addClass(incoming);
38301		}
38302	};
38303
38304	Animate.prototype.clear = function(e) {
38305		$(e.target).css( { 'left': '' } )
38306			.removeClass('animated owl-animated-out owl-animated-in')
38307			.removeClass(this.core.settings.animateIn)
38308			.removeClass(this.core.settings.animateOut);
38309		this.core.onTransitionEnd();
38310	};
38311
38312	/**
38313	 * Destroys the plugin.
38314	 * @public
38315	 */
38316	Animate.prototype.destroy = function() {
38317		var handler, property;
38318
38319		for (handler in this.handlers) {
38320			this.core.$element.off(handler, this.handlers[handler]);
38321		}
38322		for (property in Object.getOwnPropertyNames(this)) {
38323			typeof this[property] != 'function' && (this[property] = null);
38324		}
38325	};
38326
38327	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
38328
38329})(window.Zepto || window.jQuery, window, document);
38330
38331/**
38332 * Autoplay Plugin
38333 * @version 2.3.4
38334 * @author Bartosz Wojciechowski
38335 * @author Artus Kolanowski
38336 * @author David Deutsch
38337 * @author Tom De Caluwé
38338 * @license The MIT License (MIT)
38339 */
38340;(function($, window, document, undefined) {
38341
38342	/**
38343	 * Creates the autoplay plugin.
38344	 * @class The Autoplay Plugin
38345	 * @param {Owl} scope - The Owl Carousel
38346	 */
38347	var Autoplay = function(carousel) {
38348		/**
38349		 * Reference to the core.
38350		 * @protected
38351		 * @type {Owl}
38352		 */
38353		this._core = carousel;
38354
38355		/**
38356		 * The autoplay timeout id.
38357		 * @type {Number}
38358		 */
38359		this._call = null;
38360
38361		/**
38362		 * Depending on the state of the plugin, this variable contains either
38363		 * the start time of the timer or the current timer value if it's
38364		 * paused. Since we start in a paused state we initialize the timer
38365		 * value.
38366		 * @type {Number}
38367		 */
38368		this._time = 0;
38369
38370		/**
38371		 * Stores the timeout currently used.
38372		 * @type {Number}
38373		 */
38374		this._timeout = 0;
38375
38376		/**
38377		 * Indicates whenever the autoplay is paused.
38378		 * @type {Boolean}
38379		 */
38380		this._paused = true;
38381
38382		/**
38383		 * All event handlers.
38384		 * @protected
38385		 * @type {Object}
38386		 */
38387		this._handlers = {
38388			'changed.owl.carousel': $.proxy(function(e) {
38389				if (e.namespace && e.property.name === 'settings') {
38390					if (this._core.settings.autoplay) {
38391						this.play();
38392					} else {
38393						this.stop();
38394					}
38395				} else if (e.namespace && e.property.name === 'position' && this._paused) {
38396					// Reset the timer. This code is triggered when the position
38397					// of the carousel was changed through user interaction.
38398					this._time = 0;
38399				}
38400			}, this),
38401			'initialized.owl.carousel': $.proxy(function(e) {
38402				if (e.namespace && this._core.settings.autoplay) {
38403					this.play();
38404				}
38405			}, this),
38406			'play.owl.autoplay': $.proxy(function(e, t, s) {
38407				if (e.namespace) {
38408					this.play(t, s);
38409				}
38410			}, this),
38411			'stop.owl.autoplay': $.proxy(function(e) {
38412				if (e.namespace) {
38413					this.stop();
38414				}
38415			}, this),
38416			'mouseover.owl.autoplay': $.proxy(function() {
38417				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
38418					this.pause();
38419				}
38420			}, this),
38421			'mouseleave.owl.autoplay': $.proxy(function() {
38422				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
38423					this.play();
38424				}
38425			}, this),
38426			'touchstart.owl.core': $.proxy(function() {
38427				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
38428					this.pause();
38429				}
38430			}, this),
38431			'touchend.owl.core': $.proxy(function() {
38432				if (this._core.settings.autoplayHoverPause) {
38433					this.play();
38434				}
38435			}, this)
38436		};
38437
38438		// register event handlers
38439		this._core.$element.on(this._handlers);
38440
38441		// set default options
38442		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
38443	};
38444
38445	/**
38446	 * Default options.
38447	 * @public
38448	 */
38449	Autoplay.Defaults = {
38450		autoplay: false,
38451		autoplayTimeout: 5000,
38452		autoplayHoverPause: false,
38453		autoplaySpeed: false
38454	};
38455
38456	/**
38457	 * Transition to the next slide and set a timeout for the next transition.
38458	 * @private
38459	 * @param {Number} [speed] - The animation speed for the animations.
38460	 */
38461	Autoplay.prototype._next = function(speed) {
38462		this._call = window.setTimeout(
38463			$.proxy(this._next, this, speed),
38464			this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read()
38465		);
38466
38467		if (this._core.is('interacting') || document.hidden) {
38468			return;
38469		}
38470		this._core.next(speed || this._core.settings.autoplaySpeed);
38471	}
38472
38473	/**
38474	 * Reads the current timer value when the timer is playing.
38475	 * @public
38476	 */
38477	Autoplay.prototype.read = function() {
38478		return new Date().getTime() - this._time;
38479	};
38480
38481	/**
38482	 * Starts the autoplay.
38483	 * @public
38484	 * @param {Number} [timeout] - The interval before the next animation starts.
38485	 * @param {Number} [speed] - The animation speed for the animations.
38486	 */
38487	Autoplay.prototype.play = function(timeout, speed) {
38488		var elapsed;
38489
38490		if (!this._core.is('rotating')) {
38491			this._core.enter('rotating');
38492		}
38493
38494		timeout = timeout || this._core.settings.autoplayTimeout;
38495
38496		// Calculate the elapsed time since the last transition. If the carousel
38497		// wasn't playing this calculation will yield zero.
38498		elapsed = Math.min(this._time % (this._timeout || timeout), timeout);
38499
38500		if (this._paused) {
38501			// Start the clock.
38502			this._time = this.read();
38503			this._paused = false;
38504		} else {
38505			// Clear the active timeout to allow replacement.
38506			window.clearTimeout(this._call);
38507		}
38508
38509		// Adjust the origin of the timer to match the new timeout value.
38510		this._time += this.read() % timeout - elapsed;
38511
38512		this._timeout = timeout;
38513		this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed);
38514	};
38515
38516	/**
38517	 * Stops the autoplay.
38518	 * @public
38519	 */
38520	Autoplay.prototype.stop = function() {
38521		if (this._core.is('rotating')) {
38522			// Reset the clock.
38523			this._time = 0;
38524			this._paused = true;
38525
38526			window.clearTimeout(this._call);
38527			this._core.leave('rotating');
38528		}
38529	};
38530
38531	/**
38532	 * Pauses the autoplay.
38533	 * @public
38534	 */
38535	Autoplay.prototype.pause = function() {
38536		if (this._core.is('rotating') && !this._paused) {
38537			// Pause the clock.
38538			this._time = this.read();
38539			this._paused = true;
38540
38541			window.clearTimeout(this._call);
38542		}
38543	};
38544
38545	/**
38546	 * Destroys the plugin.
38547	 */
38548	Autoplay.prototype.destroy = function() {
38549		var handler, property;
38550
38551		this.stop();
38552
38553		for (handler in this._handlers) {
38554			this._core.$element.off(handler, this._handlers[handler]);
38555		}
38556		for (property in Object.getOwnPropertyNames(this)) {
38557			typeof this[property] != 'function' && (this[property] = null);
38558		}
38559	};
38560
38561	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
38562
38563})(window.Zepto || window.jQuery, window, document);
38564
38565/**
38566 * Navigation Plugin
38567 * @version 2.3.4
38568 * @author Artus Kolanowski
38569 * @author David Deutsch
38570 * @license The MIT License (MIT)
38571 */
38572;(function($, window, document, undefined) {
38573	'use strict';
38574
38575	/**
38576	 * Creates the navigation plugin.
38577	 * @class The Navigation Plugin
38578	 * @param {Owl} carousel - The Owl Carousel.
38579	 */
38580	var Navigation = function(carousel) {
38581		/**
38582		 * Reference to the core.
38583		 * @protected
38584		 * @type {Owl}
38585		 */
38586		this._core = carousel;
38587
38588		/**
38589		 * Indicates whether the plugin is initialized or not.
38590		 * @protected
38591		 * @type {Boolean}
38592		 */
38593		this._initialized = false;
38594
38595		/**
38596		 * The current paging indexes.
38597		 * @protected
38598		 * @type {Array}
38599		 */
38600		this._pages = [];
38601
38602		/**
38603		 * All DOM elements of the user interface.
38604		 * @protected
38605		 * @type {Object}
38606		 */
38607		this._controls = {};
38608
38609		/**
38610		 * Markup for an indicator.
38611		 * @protected
38612		 * @type {Array.<String>}
38613		 */
38614		this._templates = [];
38615
38616		/**
38617		 * The carousel element.
38618		 * @type {jQuery}
38619		 */
38620		this.$element = this._core.$element;
38621
38622		/**
38623		 * Overridden methods of the carousel.
38624		 * @protected
38625		 * @type {Object}
38626		 */
38627		this._overrides = {
38628			next: this._core.next,
38629			prev: this._core.prev,
38630			to: this._core.to
38631		};
38632
38633		/**
38634		 * All event handlers.
38635		 * @protected
38636		 * @type {Object}
38637		 */
38638		this._handlers = {
38639			'prepared.owl.carousel': $.proxy(function(e) {
38640				if (e.namespace && this._core.settings.dotsData) {
38641					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
38642						$(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '</div>');
38643				}
38644			}, this),
38645			'added.owl.carousel': $.proxy(function(e) {
38646				if (e.namespace && this._core.settings.dotsData) {
38647					this._templates.splice(e.position, 0, this._templates.pop());
38648				}
38649			}, this),
38650			'remove.owl.carousel': $.proxy(function(e) {
38651				if (e.namespace && this._core.settings.dotsData) {
38652					this._templates.splice(e.position, 1);
38653				}
38654			}, this),
38655			'changed.owl.carousel': $.proxy(function(e) {
38656				if (e.namespace && e.property.name == 'position') {
38657					this.draw();
38658				}
38659			}, this),
38660			'initialized.owl.carousel': $.proxy(function(e) {
38661				if (e.namespace && !this._initialized) {
38662					this._core.trigger('initialize', null, 'navigation');
38663					this.initialize();
38664					this.update();
38665					this.draw();
38666					this._initialized = true;
38667					this._core.trigger('initialized', null, 'navigation');
38668				}
38669			}, this),
38670			'refreshed.owl.carousel': $.proxy(function(e) {
38671				if (e.namespace && this._initialized) {
38672					this._core.trigger('refresh', null, 'navigation');
38673					this.update();
38674					this.draw();
38675					this._core.trigger('refreshed', null, 'navigation');
38676				}
38677			}, this)
38678		};
38679
38680		// set default options
38681		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
38682
38683		// register event handlers
38684		this.$element.on(this._handlers);
38685	};
38686
38687	/**
38688	 * Default options.
38689	 * @public
38690	 * @todo Rename `slideBy` to `navBy`
38691	 */
38692	Navigation.Defaults = {
38693		nav: false,
38694		navText: [
38695			'<span aria-label="' + 'Previous' + '">&#x2039;</span>',
38696			'<span aria-label="' + 'Next' + '">&#x203a;</span>'
38697		],
38698		navSpeed: false,
38699		navElement: 'button type="button" role="presentation"',
38700		navContainer: false,
38701		navContainerClass: 'owl-nav',
38702		navClass: [
38703			'owl-prev',
38704			'owl-next'
38705		],
38706		slideBy: 1,
38707		dotClass: 'owl-dot',
38708		dotsClass: 'owl-dots',
38709		dots: true,
38710		dotsEach: false,
38711		dotsData: false,
38712		dotsSpeed: false,
38713		dotsContainer: false
38714	};
38715
38716	/**
38717	 * Initializes the layout of the plugin and extends the carousel.
38718	 * @protected
38719	 */
38720	Navigation.prototype.initialize = function() {
38721		var override,
38722			settings = this._core.settings;
38723
38724		// create DOM structure for relative navigation
38725		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
38726			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
38727
38728		this._controls.$previous = $('<' + settings.navElement + '>')
38729			.addClass(settings.navClass[0])
38730			.html(settings.navText[0])
38731			.prependTo(this._controls.$relative)
38732			.on('click', $.proxy(function(e) {
38733				this.prev(settings.navSpeed);
38734			}, this));
38735		this._controls.$next = $('<' + settings.navElement + '>')
38736			.addClass(settings.navClass[1])
38737			.html(settings.navText[1])
38738			.appendTo(this._controls.$relative)
38739			.on('click', $.proxy(function(e) {
38740				this.next(settings.navSpeed);
38741			}, this));
38742
38743		// create DOM structure for absolute navigation
38744		if (!settings.dotsData) {
38745			this._templates = [ $('<button role="button">')
38746				.addClass(settings.dotClass)
38747				.append($('<span>'))
38748				.prop('outerHTML') ];
38749		}
38750
38751		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
38752			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
38753
38754		this._controls.$absolute.on('click', 'button', $.proxy(function(e) {
38755			var index = $(e.target).parent().is(this._controls.$absolute)
38756				? $(e.target).index() : $(e.target).parent().index();
38757
38758			e.preventDefault();
38759
38760			this.to(index, settings.dotsSpeed);
38761		}, this));
38762
38763		/*$el.on('focusin', function() {
38764			$(document).off(".carousel");
38765
38766			$(document).on('keydown.carousel', function(e) {
38767				if(e.keyCode == 37) {
38768					$el.trigger('prev.owl')
38769				}
38770				if(e.keyCode == 39) {
38771					$el.trigger('next.owl')
38772				}
38773			});
38774		});*/
38775
38776		// override public methods of the carousel
38777		for (override in this._overrides) {
38778			this._core[override] = $.proxy(this[override], this);
38779		}
38780	};
38781
38782	/**
38783	 * Destroys the plugin.
38784	 * @protected
38785	 */
38786	Navigation.prototype.destroy = function() {
38787		var handler, control, property, override, settings;
38788		settings = this._core.settings;
38789
38790		for (handler in this._handlers) {
38791			this.$element.off(handler, this._handlers[handler]);
38792		}
38793		for (control in this._controls) {
38794			if (control === '$relative' && settings.navContainer) {
38795				this._controls[control].html('');
38796			} else {
38797				this._controls[control].remove();
38798			}
38799		}
38800		for (override in this.overides) {
38801			this._core[override] = this._overrides[override];
38802		}
38803		for (property in Object.getOwnPropertyNames(this)) {
38804			typeof this[property] != 'function' && (this[property] = null);
38805		}
38806	};
38807
38808	/**
38809	 * Updates the internal state.
38810	 * @protected
38811	 */
38812	Navigation.prototype.update = function() {
38813		var i, j, k,
38814			lower = this._core.clones().length / 2,
38815			upper = lower + this._core.items().length,
38816			maximum = this._core.maximum(true),
38817			settings = this._core.settings,
38818			size = settings.center || settings.autoWidth || settings.dotsData
38819				? 1 : settings.dotsEach || settings.items;
38820
38821		if (settings.slideBy !== 'page') {
38822			settings.slideBy = Math.min(settings.slideBy, settings.items);
38823		}
38824
38825		if (settings.dots || settings.slideBy == 'page') {
38826			this._pages = [];
38827
38828			for (i = lower, j = 0, k = 0; i < upper; i++) {
38829				if (j >= size || j === 0) {
38830					this._pages.push({
38831						start: Math.min(maximum, i - lower),
38832						end: i - lower + size - 1
38833					});
38834					if (Math.min(maximum, i - lower) === maximum) {
38835						break;
38836					}
38837					j = 0, ++k;
38838				}
38839				j += this._core.mergers(this._core.relative(i));
38840			}
38841		}
38842	};
38843
38844	/**
38845	 * Draws the user interface.
38846	 * @todo The option `dotsData` wont work.
38847	 * @protected
38848	 */
38849	Navigation.prototype.draw = function() {
38850		var difference,
38851			settings = this._core.settings,
38852			disabled = this._core.items().length <= settings.items,
38853			index = this._core.relative(this._core.current()),
38854			loop = settings.loop || settings.rewind;
38855
38856		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
38857
38858		if (settings.nav) {
38859			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
38860			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
38861		}
38862
38863		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
38864
38865		if (settings.dots) {
38866			difference = this._pages.length - this._controls.$absolute.children().length;
38867
38868			if (settings.dotsData && difference !== 0) {
38869				this._controls.$absolute.html(this._templates.join(''));
38870			} else if (difference > 0) {
38871				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
38872			} else if (difference < 0) {
38873				this._controls.$absolute.children().slice(difference).remove();
38874			}
38875
38876			this._controls.$absolute.find('.active').removeClass('active');
38877			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
38878		}
38879	};
38880
38881	/**
38882	 * Extends event data.
38883	 * @protected
38884	 * @param {Event} event - The event object which gets thrown.
38885	 */
38886	Navigation.prototype.onTrigger = function(event) {
38887		var settings = this._core.settings;
38888
38889		event.page = {
38890			index: $.inArray(this.current(), this._pages),
38891			count: this._pages.length,
38892			size: settings && (settings.center || settings.autoWidth || settings.dotsData
38893				? 1 : settings.dotsEach || settings.items)
38894		};
38895	};
38896
38897	/**
38898	 * Gets the current page position of the carousel.
38899	 * @protected
38900	 * @returns {Number}
38901	 */
38902	Navigation.prototype.current = function() {
38903		var current = this._core.relative(this._core.current());
38904		return $.grep(this._pages, $.proxy(function(page, index) {
38905			return page.start <= current && page.end >= current;
38906		}, this)).pop();
38907	};
38908
38909	/**
38910	 * Gets the current succesor/predecessor position.
38911	 * @protected
38912	 * @returns {Number}
38913	 */
38914	Navigation.prototype.getPosition = function(successor) {
38915		var position, length,
38916			settings = this._core.settings;
38917
38918		if (settings.slideBy == 'page') {
38919			position = $.inArray(this.current(), this._pages);
38920			length = this._pages.length;
38921			successor ? ++position : --position;
38922			position = this._pages[((position % length) + length) % length].start;
38923		} else {
38924			position = this._core.relative(this._core.current());
38925			length = this._core.items().length;
38926			successor ? position += settings.slideBy : position -= settings.slideBy;
38927		}
38928
38929		return position;
38930	};
38931
38932	/**
38933	 * Slides to the next item or page.
38934	 * @public
38935	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
38936	 */
38937	Navigation.prototype.next = function(speed) {
38938		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
38939	};
38940
38941	/**
38942	 * Slides to the previous item or page.
38943	 * @public
38944	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
38945	 */
38946	Navigation.prototype.prev = function(speed) {
38947		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
38948	};
38949
38950	/**
38951	 * Slides to the specified item or page.
38952	 * @public
38953	 * @param {Number} position - The position of the item or page.
38954	 * @param {Number} [speed] - The time in milliseconds for the transition.
38955	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
38956	 */
38957	Navigation.prototype.to = function(position, speed, standard) {
38958		var length;
38959
38960		if (!standard && this._pages.length) {
38961			length = this._pages.length;
38962			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
38963		} else {
38964			$.proxy(this._overrides.to, this._core)(position, speed);
38965		}
38966	};
38967
38968	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
38969
38970})(window.Zepto || window.jQuery, window, document);
38971
38972/**
38973 * Hash Plugin
38974 * @version 2.3.4
38975 * @author Artus Kolanowski
38976 * @author David Deutsch
38977 * @license The MIT License (MIT)
38978 */
38979;(function($, window, document, undefined) {
38980	'use strict';
38981
38982	/**
38983	 * Creates the hash plugin.
38984	 * @class The Hash Plugin
38985	 * @param {Owl} carousel - The Owl Carousel
38986	 */
38987	var Hash = function(carousel) {
38988		/**
38989		 * Reference to the core.
38990		 * @protected
38991		 * @type {Owl}
38992		 */
38993		this._core = carousel;
38994
38995		/**
38996		 * Hash index for the items.
38997		 * @protected
38998		 * @type {Object}
38999		 */
39000		this._hashes = {};
39001
39002		/**
39003		 * The carousel element.
39004		 * @type {jQuery}
39005		 */
39006		this.$element = this._core.$element;
39007
39008		/**
39009		 * All event handlers.
39010		 * @protected
39011		 * @type {Object}
39012		 */
39013		this._handlers = {
39014			'initialized.owl.carousel': $.proxy(function(e) {
39015				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
39016					$(window).trigger('hashchange.owl.navigation');
39017				}
39018			}, this),
39019			'prepared.owl.carousel': $.proxy(function(e) {
39020				if (e.namespace) {
39021					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
39022
39023					if (!hash) {
39024						return;
39025					}
39026
39027					this._hashes[hash] = e.content;
39028				}
39029			}, this),
39030			'changed.owl.carousel': $.proxy(function(e) {
39031				if (e.namespace && e.property.name === 'position') {
39032					var current = this._core.items(this._core.relative(this._core.current())),
39033						hash = $.map(this._hashes, function(item, hash) {
39034							return item === current ? hash : null;
39035						}).join();
39036
39037					if (!hash || window.location.hash.slice(1) === hash) {
39038						return;
39039					}
39040
39041					window.location.hash = hash;
39042				}
39043			}, this)
39044		};
39045
39046		// set default options
39047		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
39048
39049		// register the event handlers
39050		this.$element.on(this._handlers);
39051
39052		// register event listener for hash navigation
39053		$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
39054			var hash = window.location.hash.substring(1),
39055				items = this._core.$stage.children(),
39056				position = this._hashes[hash] && items.index(this._hashes[hash]);
39057
39058			if (position === undefined || position === this._core.current()) {
39059				return;
39060			}
39061
39062			this._core.to(this._core.relative(position), false, true);
39063		}, this));
39064	};
39065
39066	/**
39067	 * Default options.
39068	 * @public
39069	 */
39070	Hash.Defaults = {
39071		URLhashListener: false
39072	};
39073
39074	/**
39075	 * Destroys the plugin.
39076	 * @public
39077	 */
39078	Hash.prototype.destroy = function() {
39079		var handler, property;
39080
39081		$(window).off('hashchange.owl.navigation');
39082
39083		for (handler in this._handlers) {
39084			this._core.$element.off(handler, this._handlers[handler]);
39085		}
39086		for (property in Object.getOwnPropertyNames(this)) {
39087			typeof this[property] != 'function' && (this[property] = null);
39088		}
39089	};
39090
39091	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
39092
39093})(window.Zepto || window.jQuery, window, document);
39094
39095/**
39096 * Support Plugin
39097 *
39098 * @version 2.3.4
39099 * @author Vivid Planet Software GmbH
39100 * @author Artus Kolanowski
39101 * @author David Deutsch
39102 * @license The MIT License (MIT)
39103 */
39104;(function($, window, document, undefined) {
39105
39106	var style = $('<support>').get(0).style,
39107		prefixes = 'Webkit Moz O ms'.split(' '),
39108		events = {
39109			transition: {
39110				end: {
39111					WebkitTransition: 'webkitTransitionEnd',
39112					MozTransition: 'transitionend',
39113					OTransition: 'oTransitionEnd',
39114					transition: 'transitionend'
39115				}
39116			},
39117			animation: {
39118				end: {
39119					WebkitAnimation: 'webkitAnimationEnd',
39120					MozAnimation: 'animationend',
39121					OAnimation: 'oAnimationEnd',
39122					animation: 'animationend'
39123				}
39124			}
39125		},
39126		tests = {
39127			csstransforms: function() {
39128				return !!test('transform');
39129			},
39130			csstransforms3d: function() {
39131				return !!test('perspective');
39132			},
39133			csstransitions: function() {
39134				return !!test('transition');
39135			},
39136			cssanimations: function() {
39137				return !!test('animation');
39138			}
39139		};
39140
39141	function test(property, prefixed) {
39142		var result = false,
39143			upper = property.charAt(0).toUpperCase() + property.slice(1);
39144
39145		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
39146			if (style[property] !== undefined) {
39147				result = prefixed ? property : true;
39148				return false;
39149			}
39150		});
39151
39152		return result;
39153	}
39154
39155	function prefixed(property) {
39156		return test(property, true);
39157	}
39158
39159	if (tests.csstransitions()) {
39160		/* jshint -W053 */
39161		$.support.transition = new String(prefixed('transition'))
39162		$.support.transition.end = events.transition.end[ $.support.transition ];
39163	}
39164
39165	if (tests.cssanimations()) {
39166		/* jshint -W053 */
39167		$.support.animation = new String(prefixed('animation'))
39168		$.support.animation.end = events.animation.end[ $.support.animation ];
39169	}
39170
39171	if (tests.csstransforms()) {
39172		/* jshint -W053 */
39173		$.support.transform = new String(prefixed('transform'));
39174		$.support.transform3d = tests.csstransforms3d();
39175	}
39176
39177})(window.Zepto || window.jQuery, window, document);
39178
39179/*!
39180	autosize 4.0.2
39181	license: MIT
39182	http://www.jacklmoore.com/autosize
39183*/
39184(function (global, factory) {
39185	if (typeof define === "function" && define.amd) {
39186		define(['module', 'exports'], factory);
39187	} else if (typeof exports !== "undefined") {
39188		factory(module, exports);
39189	} else {
39190		var mod = {
39191			exports: {}
39192		};
39193		factory(mod, mod.exports);
39194		global.autosize = mod.exports;
39195	}
39196})(this, function (module, exports) {
39197	'use strict';
39198
39199	var map = typeof Map === "function" ? new Map() : function () {
39200		var keys = [];
39201		var values = [];
39202
39203		return {
39204			has: function has(key) {
39205				return keys.indexOf(key) > -1;
39206			},
39207			get: function get(key) {
39208				return values[keys.indexOf(key)];
39209			},
39210			set: function set(key, value) {
39211				if (keys.indexOf(key) === -1) {
39212					keys.push(key);
39213					values.push(value);
39214				}
39215			},
39216			delete: function _delete(key) {
39217				var index = keys.indexOf(key);
39218				if (index > -1) {
39219					keys.splice(index, 1);
39220					values.splice(index, 1);
39221				}
39222			}
39223		};
39224	}();
39225
39226	var createEvent = function createEvent(name) {
39227		return new Event(name, { bubbles: true });
39228	};
39229	try {
39230		new Event('test');
39231	} catch (e) {
39232		// IE does not support `new Event()`
39233		createEvent = function createEvent(name) {
39234			var evt = document.createEvent('Event');
39235			evt.initEvent(name, true, false);
39236			return evt;
39237		};
39238	}
39239
39240	function assign(ta) {
39241		if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) return;
39242
39243		var heightOffset = null;
39244		var clientWidth = null;
39245		var cachedHeight = null;
39246
39247		function init() {
39248			var style = window.getComputedStyle(ta, null);
39249
39250			if (style.resize === 'vertical') {
39251				ta.style.resize = 'none';
39252			} else if (style.resize === 'both') {
39253				ta.style.resize = 'horizontal';
39254			}
39255
39256			if (style.boxSizing === 'content-box') {
39257				heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
39258			} else {
39259				heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
39260			}
39261			// Fix when a textarea is not on document body and heightOffset is Not a Number
39262			if (isNaN(heightOffset)) {
39263				heightOffset = 0;
39264			}
39265
39266			update();
39267		}
39268
39269		function changeOverflow(value) {
39270			{
39271				// Chrome/Safari-specific fix:
39272				// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
39273				// made available by removing the scrollbar. The following forces the necessary text reflow.
39274				var width = ta.style.width;
39275				ta.style.width = '0px';
39276				// Force reflow:
39277				/* jshint ignore:start */
39278				ta.offsetWidth;
39279				/* jshint ignore:end */
39280				ta.style.width = width;
39281			}
39282
39283			ta.style.overflowY = value;
39284		}
39285
39286		function getParentOverflows(el) {
39287			var arr = [];
39288
39289			while (el && el.parentNode && el.parentNode instanceof Element) {
39290				if (el.parentNode.scrollTop) {
39291					arr.push({
39292						node: el.parentNode,
39293						scrollTop: el.parentNode.scrollTop
39294					});
39295				}
39296				el = el.parentNode;
39297			}
39298
39299			return arr;
39300		}
39301
39302		function resize() {
39303			if (ta.scrollHeight === 0) {
39304				// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
39305				return;
39306			}
39307
39308			var overflows = getParentOverflows(ta);
39309			var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)
39310
39311			ta.style.height = '';
39312			ta.style.height = ta.scrollHeight + heightOffset + 'px';
39313
39314			// used to check if an update is actually necessary on window.resize
39315			clientWidth = ta.clientWidth;
39316
39317			// prevents scroll-position jumping
39318			overflows.forEach(function (el) {
39319				el.node.scrollTop = el.scrollTop;
39320			});
39321
39322			if (docTop) {
39323				document.documentElement.scrollTop = docTop;
39324			}
39325		}
39326
39327		function update() {
39328			resize();
39329
39330			var styleHeight = Math.round(parseFloat(ta.style.height));
39331			var computed = window.getComputedStyle(ta, null);
39332
39333			// Using offsetHeight as a replacement for computed.height in IE, because IE does not account use of border-box
39334			var actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(computed.height)) : ta.offsetHeight;
39335
39336			// The actual height not matching the style height (set via the resize method) indicates that 
39337			// the max-height has been exceeded, in which case the overflow should be allowed.
39338			if (actualHeight < styleHeight) {
39339				if (computed.overflowY === 'hidden') {
39340					changeOverflow('scroll');
39341					resize();
39342					actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
39343				}
39344			} else {
39345				// Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
39346				if (computed.overflowY !== 'hidden') {
39347					changeOverflow('hidden');
39348					resize();
39349					actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
39350				}
39351			}
39352
39353			if (cachedHeight !== actualHeight) {
39354				cachedHeight = actualHeight;
39355				var evt = createEvent('autosize:resized');
39356				try {
39357					ta.dispatchEvent(evt);
39358				} catch (err) {
39359					// Firefox will throw an error on dispatchEvent for a detached element
39360					// https://bugzilla.mozilla.org/show_bug.cgi?id=889376
39361				}
39362			}
39363		}
39364
39365		var pageResize = function pageResize() {
39366			if (ta.clientWidth !== clientWidth) {
39367				update();
39368			}
39369		};
39370
39371		var destroy = function (style) {
39372			window.removeEventListener('resize', pageResize, false);
39373			ta.removeEventListener('input', update, false);
39374			ta.removeEventListener('keyup', update, false);
39375			ta.removeEventListener('autosize:destroy', destroy, false);
39376			ta.removeEventListener('autosize:update', update, false);
39377
39378			Object.keys(style).forEach(function (key) {
39379				ta.style[key] = style[key];
39380			});
39381
39382			map.delete(ta);
39383		}.bind(ta, {
39384			height: ta.style.height,
39385			resize: ta.style.resize,
39386			overflowY: ta.style.overflowY,
39387			overflowX: ta.style.overflowX,
39388			wordWrap: ta.style.wordWrap
39389		});
39390
39391		ta.addEventListener('autosize:destroy', destroy, false);
39392
39393		// IE9 does not fire onpropertychange or oninput for deletions,
39394		// so binding to onkeyup to catch most of those events.
39395		// There is no way that I know of to detect something like 'cut' in IE9.
39396		if ('onpropertychange' in ta && 'oninput' in ta) {
39397			ta.addEventListener('keyup', update, false);
39398		}
39399
39400		window.addEventListener('resize', pageResize, false);
39401		ta.addEventListener('input', update, false);
39402		ta.addEventListener('autosize:update', update, false);
39403		ta.style.overflowX = 'hidden';
39404		ta.style.wordWrap = 'break-word';
39405
39406		map.set(ta, {
39407			destroy: destroy,
39408			update: update
39409		});
39410
39411		init();
39412	}
39413
39414	function destroy(ta) {
39415		var methods = map.get(ta);
39416		if (methods) {
39417			methods.destroy();
39418		}
39419	}
39420
39421	function update(ta) {
39422		var methods = map.get(ta);
39423		if (methods) {
39424			methods.update();
39425		}
39426	}
39427
39428	var autosize = null;
39429
39430	// Do nothing in Node.js environment and IE8 (or lower)
39431	if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
39432		autosize = function autosize(el) {
39433			return el;
39434		};
39435		autosize.destroy = function (el) {
39436			return el;
39437		};
39438		autosize.update = function (el) {
39439			return el;
39440		};
39441	} else {
39442		autosize = function autosize(el, options) {
39443			if (el) {
39444				Array.prototype.forEach.call(el.length ? el : [el], function (x) {
39445					return assign(x, options);
39446				});
39447			}
39448			return el;
39449		};
39450		autosize.destroy = function (el) {
39451			if (el) {
39452				Array.prototype.forEach.call(el.length ? el : [el], destroy);
39453			}
39454			return el;
39455		};
39456		autosize.update = function (el) {
39457			if (el) {
39458				Array.prototype.forEach.call(el.length ? el : [el], update);
39459			}
39460			return el;
39461		};
39462	}
39463
39464	exports.default = autosize;
39465	module.exports = exports['default'];
39466});
39467/*!
39468 * clipboard.js v2.0.4
39469 * https://zenorocha.github.io/clipboard.js
39470 * 
39471 * Licensed MIT © Zeno Rocha
39472 */
39473!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exp
39473orts.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}}(),a=o(n(1)),c=o(n(3)),u=o(n(4));function o(t){return t&&t.__esModule?t:{default:t}}var l=function(t){function o(t,e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));return n.resolveOptions(e),n.listenClick(t),n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,c.default),i(o,[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===r(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=(0,u.default)(t,"click",function(t){return e.onClick(t)})}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new a.default({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return s("action",t)}},{key:"defaultTarget",value:function(t){var e=s("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return s("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported;return e.forEach(function(t){n=n&&!!document.queryCommandSupported(t)}),n}}]),o}();function s(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}t.exports=l},function(t,e,n){"use strict";var o,r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}}(),a=n(2),c=(o=a)&&o.__esModule?o:{default:o};var u=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.resolveOptions(t),this.initSelection()}return i(e,[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}}
vendor: 2,910 bytes, line 39473
39473,{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,c.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=(0,c.default)(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==(void 0===t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),e}();t.exports=u},function(t,e){t.exports=function(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly");n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}
39473else{t.hasAttribute("contenteditable")&&t.focus();var o=window.getSelection(),r=document.createRange();r.selectNodeContents(t),o.removeAllRanges(),o.addRange(r),e=o.toString()}return e}},function(t,e){function n(){}n.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var o=this;function r(){o.off(t,r),e.apply(n,arguments)}return r._=e,this.on(t,r,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,r=n.length;o<r;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],r=[];if(o&&e)for(var i=0,a=o.length;i<a;i++)o[i].fn!==e&&o[i].fn._!==e&&r.push(o[i]);return r.length?n[t]=r:delete n[t],this}},t.exports=n},function(t,e,n){var d=n(5),h=n(6);t.exports=function(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!d.string(e))throw new TypeError("Second argument must be a String");if(!d.fn(n))throw new TypeError("Third argument must be a Function");if(d.node(t))return s=e,f=n,(l=t).addEventListener(s,f),{destroy:function(){l.removeEventListener(s,f)}};if(d.nodeList(t))return a=t,c=e,u=n,Array.prototype.forEach.call(a,function(t){t.addEventListener(c,u)}),{destroy:function(){Array.prototype.forEach.call(a,function(t){t.removeEventListener(c,u)})}};if(d.string(t))return o=t,r=e,i=n,h(document.body,o,r,i);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList");var o,r,i,a,c,u,l,s,f}},function(t,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){return"[object Function]"===Object.prototype.toString.call(t)}},function(t,e,n){var a=n(7);function i(t,e,n,o,r){var i=function(e,n,t,o){return function(t){t.delegateTarget=a(t.target,n),t.delegateTarget&&o.call(e,t)}}.apply(this,arguments);return t.addEventListener(n,i,r),{destroy:function(){t.removeEventListener(n,i,r)}}}t.exports=function(t,e,n,o,r){return"function"==typeof t.addEventListener?i.apply(null,arguments):"function"==typeof n?i.bind(null,document).apply(null,arguments):("string"==typeof t&&(t=document.querySelectorAll(t)),Array.prototype.map.call(t,function(t){return i(t,e,n,o,r)}))}},function(t,e){if("undefined"!=typeof Element&&!Element.prototype.matches){var n=Element.prototype;n.matches=n.matchesSelector||n.mozMatchesSelector||n.msMatchesSelector||n.oMatchesSelector||n.webkitMatchesSelector}t.exports=function(t,e){for(;t&&9!==t.nodeType;){if("function"==typeof t.matches&&t.matches(e))return t;t=t.parentNode}}}])});
39474"use strict";
39475
39476var _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; }; }();
39477
39478function _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; }
39479
39480function _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; }
39481
39482function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
39483
39484/*
39485 *
39486 * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
39487 *
39488 * Copyright (c) 2012, Matias Meno
39489 *
39490 * Permission is hereby granted, free of charge, to any person obtaining a copy
39491 * of this software and associated documentation files (the "Software"), to deal
39492 * in the Software without restriction, including without limitation the rights
39493 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39494 * copies of the Software, and to permit persons to whom the Software is
39495 * furnished to do so, subject to the following conditions:
39496 *
39497 * The above copyright notice and this permission notice shall be included in
39498 * all copies or substantial portions of the Software.
39499 *
39500 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39501 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39502 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39503 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39504 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39505 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39506 * THE SOFTWARE.
39507 *
39508 */
39509
39510// The Emitter class provides the ability to call `.on()` on Dropzone to listen
39511// to events.
39512// It is strongly based on component's emitter class, and I removed the
39513// functionality because of the dependency hell with different frameworks.
39514var Emitter = function () {
39515  function Emitter() {
39516    _classCallCheck(this, Emitter);
39517  }
39518
39519  _createClass(Emitter, [{
39520    key: "on",
39521
39522    // Add an event listener for given event
39523    value: function on(event, fn) {
39524      this._callbacks = this._callbacks || {};
39525      // Create namespace for this event
39526      if (!this._callbacks[event]) {
39527        this._callbacks[event] = [];
39528      }
39529      this._callbacks[event].push(fn);
39530      return this;
39531    }
39532  }, {
39533    key: "emit",
39534    value: function emit(event) {
39535      this._callbacks = this._callbacks || {};
39536      var callbacks = this._callbacks[event];
39537
39538      if (callbacks) {
39539        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
39540          args[_key - 1] = arguments[_key];
39541        }
39542
39543        for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
39544          var _ref;
39545
39546          if (_isArray) {
39547            if (_i >= _iterator.length) break;
39548            _ref = _iterator[_i++];
39549          } else {
39550            _i = _iterator.next();
39551            if (_i.done) break;
39552            _ref = _i.value;
39553          }
39554
39555          var callback = _ref;
39556
39557          callback.apply(this, args);
39558        }
39559      }
39560
39561      return this;
39562    }
39563
39564    // Remove event listener for given event. If fn is not provided, all event
39565    // listeners for that event will be removed. If neither is provided, all
39566    // event listeners will be removed.
39567
39568  }, {
39569    key: "off",
39570    value: function off(event, fn) {
39571      if (!this._callbacks || arguments.length === 0) {
39572        this._callbacks = {};
39573        return this;
39574      }
39575
39576      // specific event
39577      var callbacks = this._callbacks[event];
39578      if (!callbacks) {
39579        return this;
39580      }
39581
39582      // remove all handlers
39583      if (arguments.length === 1) {
39584        delete this._callbacks[event];
39585        return this;
39586      }
39587
39588      // remove specific handler
39589      for (var i = 0; i < callbacks.length; i++) {
39590        var callback = callbacks[i];
39591        if (callback === fn) {
39592          callbacks.splice(i, 1);
39593          break;
39594        }
39595      }
39596
39597      return this;
39598    }
39599  }]);
39600
39601  return Emitter;
39602}();
39603
39604var Dropzone = function (_Emitter) {
39605  _inherits(Dropzone, _Emitter);
39606
39607  _createClass(Dropzone, null, [{
39608    key: "initClass",
39609    value: function initClass() {
39610
39611      // Exposing the emitter class, mainly for tests
39612      this.prototype.Emitter = Emitter;
39613
39614      /*
39615       This is a list of all available events you can register on a dropzone object.
39616        You can register an event handler like this:
39617        dropzone.on("dragEnter", function() { });
39618        */
39619      this.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
39620
39621      this.prototype.defaultOptions = {
39622        /**
39623         * Has to be specified on elements other than form (or when the form
39624         * doesn't have an `action` attribute). You can also
39625         * provide a function that will be called with `files` and
39626         * must return the url (since `v3.12.0`)
39627         */
39628        url: null,
39629
39630        /**
39631         * Can be changed to `"put"` if necessary. You can also provide a function
39632         * that will be called with `files` and must return the method (since `v3.12.0`).
39633         */
39634        method: "post",
39635
39636        /**
39637         * Will be set on the XHRequest.
39638         */
39639        withCredentials: false,
39640
39641        /**
39642         * The timeout for the XHR requests in milliseconds (since `v4.4.0`).
39643         */
39644        timeout: 30000,
39645
39646        /**
39647         * How many file uploads to process in parallel (See the
39648         * Enqueuing file uploads* documentation section for more info)
39649         */
39650        parallelUploads: 2,
39651
39652        /**
39653         * Whether to send multiple files in one request. If
39654         * this it set to true, then the fallback file input element will
39655         * have the `multiple` attribute as well. This option will
39656         * also trigger additional events (like `processingmultiple`). See the events
39657         * documentation section for more information.
39658         */
39659        uploadMultiple: false,
39660
39661        /**
39662         * Whether you want files to be uploaded in chunks to your server. This can't be
39663         * used in combination with `uploadMultiple`.
39664         *
39665         * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.
39666         */
39667        chunking: false,
39668
39669        /**
39670         * If `chunking` is enabled, this defines whether **every** file should be chunked,
39671         * even if the file size is below chunkSize. This means, that the additional chunk
39672         * form data will be submitted and the `chunksUploaded` callback will be invoked.
39673         */
39674        forceChunking: false,
39675
39676        /**
39677         * If `chunking` is `true`, then this defines the chunk size in bytes.
39678         */
39679        chunkSize: 2000000,
39680
39681        /**
39682         * If `true`, the individual chunks of a file are being uploaded simultaneously.
39683         */
39684        parallelChunkUploads: false,
39685
39686        /**
39687         * Whether a chunk should be retried if it fails.
39688         */
39689        retryChunks: false,
39690
39691        /**
39692         * If `retryChunks` is true, how many times should it be retried.
39693         */
39694        retryChunksLimit: 3,
39695
39696        /**
39697         * If not `null` defines how many files this Dropzone handles. If it exceeds,
39698         * the event `maxfilesexceeded` will be called. The dropzone element gets the
39699         * class `dz-max-files-reached` accordingly so you can provide visual feedback.
39700         */
39701        maxFilesize: 256,
39702
39703        /**
39704         * The name of the file param that gets transferred.
39705         * **NOTE**: If you have the option  `uploadMultiple` set to `true`, then
39706         * Dropzone will append `[]` to the name.
39707         */
39708        paramName: "file",
39709
39710        /**
39711         * Whether thumbnails for images should be generated
39712         */
39713        createImageThumbnails: true,
39714
39715        /**
39716         * In MB. When the filename exceeds this limit, the thumbnail will not be generated.
39717         */
39718        maxThumbnailFilesize: 10,
39719
39720        /**
39721         * If `null`, the ratio of the image will be used to calculate it.
39722         */
39723        thumbnailWidth: 120,
39724
39725        /**
39726         * The same as `thumbnailWidth`. If both are null, images will not be resized.
39727         */
39728        thumbnailHeight: 120,
39729
39730        /**
39731         * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.
39732         * Can be either `contain` or `crop`.
39733         */
39734        thumbnailMethod: 'crop',
39735
39736        /**
39737         * If set, images will be resized to these dimensions before being **uploaded**.
39738         * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect
39739         * ratio of the file will be preserved.
39740         *
39741         * The `options.transformFile` function uses these options, so if the `transformFile` function
39742         * is overridden, these options don't do anything.
39743         */
39744        resizeWidth: null,
39745
39746        /**
39747         * See `resizeWidth`.
39748         */
39749        resizeHeight: null,
39750
39751        /**
39752         * The mime type of the resized image (before it gets uploaded to the server).
39753         * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.
39754         * See `resizeWidth` for more information.
39755         */
39756        resizeMimeType: null,
39757
39758        /**
39759         * The quality of the resized images. See `resizeWidth`.
39760         */
39761        resizeQuality: 0.8,
39762
39763        /**
39764         * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.
39765         * Can be either `contain` or `crop`.
39766         */
39767        resizeMethod: 'contain',
39768
39769        /**
39770         * The base that is used to calculate the filesize. You can change this to
39771         * 1024 if you would rather display kibibytes, mebibytes, etc...
39772         * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.
39773         * You can change this to `1024` if you don't care about validity.
39774         */
39775        filesizeBase: 1000,
39776
39777        /**
39778         * Can be used to limit the maximum number of files that will be handled by this Dropzone
39779         */
39780        maxFiles: null,
39781
39782        /**
39783         * An optional object to send additional headers to the server. Eg:
39784         * `{ "My-Awesome-Header": "header value" }`
39785         */
39786        headers: null,
39787
39788        /**
39789         * If `true`, the dropzone element itself will be clickable, if `false`
39790         * nothing will be clickable.
39791         *
39792         * You can also pass an HTML element, a CSS selector (for multiple elements)
39793         * or an array of those. In that case, all of those elements will trigger an
39794         * upload when clicked.
39795         */
39796        clickable: true,
39797
39798        /**
39799         * Whether hidden files in directories should be ignored.
39800         */
39801        ignoreHiddenFiles: true,
39802
39803        /**
39804         * The default implementation of `accept` checks the file's mime type or
39805         * extension against this list. This is a comma separated list of mime
39806         * types or file extensions.
39807         *
39808         * Eg.: `image/*,application/pdf,.psd`
39809         *
39810         * If the Dropzone is `clickable` this option will also be used as
39811         * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)
39812         * parameter on the hidden file input as well.
39813         */
39814        acceptedFiles: null,
39815
39816        /**
39817         * **Deprecated!**
39818         * Use acceptedFiles instead.
39819         */
39820        acceptedMimeTypes: null,
39821
39822        /**
39823         * If false, files will be added to the queue but the queue will not be
39824         * processed automatically.
39825         * This can be useful if you need some additional user input before sending
39826         * files (or if you want want all files sent at once).
39827         * If you're ready to send the file simply call `myDropzone.processQueue()`.
39828         *
39829         * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation
39830         * section for more information.
39831         */
39832        autoProcessQueue: true,
39833
39834        /**
39835         * If false, files added to the dropzone will not be queued by default.
39836         * You'll have to call `enqueueFile(file)` manually.
39837         */
39838        autoQueue: true,
39839
39840        /**
39841         * If `true`, this will add a link to every file preview to remove or cancel (if
39842         * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`
39843         * and `dictRemoveFile` options are used for the wording.
39844         */
39845        addRemoveLinks: false,
39846
39847        /**
39848         * Defines where to display the file previews – if `null` the
39849         * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS
39850         * selector. The element should have the `dropzone-previews` class so
39851         * the previews are displayed properly.
39852         */
39853        previewsContainer: null,
39854
39855        /**
39856         * This is the element the hidden input field (which is used when clicking on the
39857         * dropzone to trigger file selection) will be appended to. This might
39858         * be important in case you use frameworks to switch the content of your page.
39859         *
39860         * Can be a selector string, or an element directly.
39861         */
39862        hiddenInputContainer: "body",
39863
39864        /**
39865         * If null, no capture type will be specified
39866         * If camera, mobile devices will skip the file selection and choose camera
39867         * If microphone, mobile devices will skip the file selection and choose the microphone
39868         * If camcorder, mobile devices will skip the file selection and choose the camera in video mode
39869         * On apple devices multiple must be set to false.  AcceptedFiles may need to
39870         * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").
39871         */
39872        capture: null,
39873
39874        /**
39875         * **Deprecated**. Use `renameFile` instead.
39876         */
39877        renameFilename: null,
39878
39879        /**
39880         * A function that is invoked before the file is uploaded to the server and renames the file.
39881         * This function gets the `File` as argument and can use the `file.name`. The actual name of the
39882         * file that gets used during the upload can be accessed through `file.upload.filename`.
39883         */
39884        renameFile: null,
39885
39886        /**
39887         * If `true` the fallback will be forced. This is very useful to test your server
39888         * implementations first and make sure that everything works as
39889         * expected without dropzone if you experience problems, and to test
39890         * how your fallbacks will look.
39891         */
39892        forceFallback: false,
39893
39894        /**
39895         * The text used before any files are dropped.
39896         */
39897        dictDefaultMessage: "Drop files here to upload",
39898
39899        /**
39900         * The text that replaces the default message text it the browser is not supported.
39901         */
39902        dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
39903
39904        /**
39905         * The text that will be added before the fallback form.
39906         * If you provide a  fallback element yourself, or if this option is `null` this will
39907         * be ignored.
39908         */
39909        dictFallbackText: "Please use the fallback form below to upload your files like in the olde
39909n days.",
39910
39911        /**
39912         * If the filesize is too big.
39913         * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.
39914         */
39915        dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
39916
39917        /**
39918         * If the file doesn't match the file type.
39919         */
39920        dictInvalidFileType: "You can't upload files of this type.",
39921
39922        /**
39923         * If the server response was invalid.
39924         * `{{statusCode}}` will be replaced with the servers status code.
39925         */
39926        dictResponseError: "Server responded with {{statusCode}} code.",
39927
39928        /**
39929         * If `addRemoveLinks` is true, the text to be used for the cancel upload link.
39930         */
39931        dictCancelUpload: "Cancel upload",
39932
39933        /**
39934         * The text that is displayed if an upload was manually canceled
39935         */
39936        dictUploadCanceled: "Upload canceled.",
39937
39938        /**
39939         * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.
39940         */
39941        dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
39942
39943        /**
39944         * If `addRemoveLinks` is true, the text to be used to remove a file.
39945         */
39946        dictRemoveFile: "Remove file",
39947
39948        /**
39949         * If this is not null, then the user will be prompted before removing a file.
39950         */
39951        dictRemoveFileConfirmation: null,
39952
39953        /**
39954         * Displayed if `maxFiles` is st and exceeded.
39955         * The string `{{maxFiles}}` will be replaced by the configuration value.
39956         */
39957        dictMaxFilesExceeded: "You can not upload any more files.",
39958
39959        /**
39960         * Allows you to translate the different units. Starting with `tb` for terabytes and going down to
39961         * `b` for bytes.
39962         */
39963        dictFileSizeUnits: { tb: "TB", gb: "GB", mb: "MB", kb: "KB", b: "b" },
39964        /**
39965         * Called when dropzone initialized
39966         * You can add event listeners here
39967         */
39968        init: function init() {},
39969
39970
39971        /**
39972         * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`
39973         * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case
39974         * of a function, this needs to return a map.
39975         *
39976         * The default implementation does nothing for normal uploads, but adds relevant information for
39977         * chunked uploads.
39978         *
39979         * This is the same as adding hidden input fields in the form element.
39980         */
39981        params: function params(files, xhr, chunk) {
39982          if (chunk) {
39983            return {
39984              dzuuid: chunk.file.upload.uuid,
39985              dzchunkindex: chunk.index,
39986              dztotalfilesize: chunk.file.size,
39987              dzchunksize: this.options.chunkSize,
39988              dztotalchunkcount: chunk.file.upload.totalChunkCount,
39989              dzchunkbyteoffset: chunk.index * this.options.chunkSize
39990            };
39991          }
39992        },
39993
39994
39995        /**
39996         * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)
39997         * and a `done` function as parameters.
39998         *
39999         * If the done function is invoked without arguments, the file is "accepted" and will
40000         * be processed. If you pass an error message, the file is rejected, and the error
40001         * message will be displayed.
40002         * This function will not be called if the file is too big or doesn't match the mime types.
40003         */
40004        accept: function accept(file, done) {
40005          return done();
40006        },
40007
40008
40009        /**
40010         * The callback that will be invoked when all chunks have been uploaded for a file.
40011         * It gets the file for which the chunks have been uploaded as the first parameter,
40012         * and the `done` function as second. `done()` needs to be invoked when everything
40013         * needed to finish the upload process is done.
40014         */
40015        chunksUploaded: function chunksUploaded(file, done) {
40016          done();
40017        },
40018
40019        /**
40020         * Gets called when the browser is not supported.
40021         * The default implementation shows the fallback input field and adds
40022         * a text.
40023         */
40024        fallback: function fallback() {
40025          // This code should pass in IE7... :(
40026          var messageElement = void 0;
40027          this.element.className = this.element.className + " dz-browser-not-supported";
40028
40029          for (var _iterator2 = this.element.getElementsByTagName("div"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
40030            var _ref2;
40031
40032            if (_isArray2) {
40033              if (_i2 >= _iterator2.length) break;
40034              _ref2 = _iterator2[_i2++];
40035            } else {
40036              _i2 = _iterator2.next();
40037              if (_i2.done) break;
40038              _ref2 = _i2.value;
40039            }
40040
40041            var child = _ref2;
40042
40043            if (/(^| )dz-message($| )/.test(child.className)) {
40044              messageElement = child;
40045              child.className = "dz-message"; // Removes the 'dz-default' class
40046              break;
40047            }
40048          }
40049          if (!messageElement) {
40050            messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
40051            this.element.appendChild(messageElement);
40052          }
40053
40054          var span = messageElement.getElementsByTagName("span")[0];
40055          if (span) {
40056            if (span.textContent != null) {
40057              span.textContent = this.options.dictFallbackMessage;
40058            }
40058 else if (span.innerText != null) {
40059              span.innerText = this.options.dictFallbackMessage;
40060            }
40061          }
40062
40063          return this.element.appendChild(this.getFallbackForm());
40064        },
40065
40066
40067        /**
40068         * Gets called to calculate the thumbnail dimensions.
40069         *
40070         * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:
40071         *
40072         *  - `srcWidth` & `srcHeight` (required)
40073         *  - `trgWidth` & `trgHeight` (required)
40074         *  - `srcX` & `srcY` (optional, default `0`)
40075         *  - `trgX` & `trgY` (optional, default `0`)
40076         *
40077         * Those values are going to be used by `ctx.drawImage()`.
40078         */
40079        resize: function resize(file, width, height, resizeMethod) {
40080          var info = {
40081            srcX: 0,
40082            srcY: 0,
40083            srcWidth: file.width,
40084            srcHeight: file.height
40085          };
40086
40087          var srcRatio = file.width / file.height;
40088
40089          // Automatically calculate dimensions if not specified
40090          if (width == null && height == null) {
40091            width = info.srcWidth;
40092            height = info.srcHeight;
40093          } else if (width == null) {
40094            width = height * srcRatio;
40095          } else if (height == null) {
40096            height = width / srcRatio;
40097          }
40098
40099          // Make sure images aren't upscaled
40100          width = Math.min(width, info.srcWidth);
40101          height = Math.min(height, info.srcHeight);
40102
40103          var trgRatio = width / height;
40104
40105          if (info.srcWidth > width || info.srcHeight > height) {
40106            // Image is bigger and needs rescaling
40107            if (resizeMethod === 'crop') {
40108              if (srcRatio > trgRatio) {
40109                info.srcHeight = file.height;
40110                info.srcWidth = info.srcHeight * trgRatio;
40111              } else {
40112                info.srcWidth = file.width;
40113                info.srcHeight = info.srcWidth / trgRatio;
40114              }
40115            } else if (resizeMethod === 'contain') {
40116              // Method 'contain'
40117              if (srcRatio > trgRatio) {
40118                height = width / srcRatio;
40119              } else {
40120                width = height * srcRatio;
40121              }
40122            } else {
40123              throw new Error("Unknown resizeMethod '" + resizeMethod + "'");
40124            }
40125          }
40126
40127          info.srcX = (file.width - info.srcWidth) / 2;
40128          info.srcY = (file.height - info.srcHeight) / 2;
40129
40130          info.trgWidth = width;
40131          info.trgHeight = height;
40132
40133          return info;
40134        },
40135
40136
40137        /**
40138         * Can be used to transform the file (for example, resize an image if necessary).
40139         *
40140         * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes
40141         * images according to those dimensions.
40142         *
40143         * Gets the `file` as the first parameter, and a `done()` function as the second, that needs
40144         * to be invoked with the file when the transformation is done.
40145         */
40146        transformFile: function transformFile(file, done) {
40147          if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
40148            return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
40149          } else {
40150            return done(file);
40151          }
40152        },
40153
40154
40155        /**
40156         * A string that contains the template used for each dropped
40157         * file. Change it to fulfill your needs but make sure to properly
40158         * provide all elements.
40159         *
40160         * If you want to use an actual HTML element instead of providing a String
40161         * as a config option, you could create a div with the id `tpl`,
40162         * put the template inside it and provide the element like this:
40163         *
40164         *     document
40165         *       .querySelector('#tpl')
40166         *       .innerHTML
40167         *
40168         */
40169        previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n  <div class=\"dz-details\">\n    <div class=\"dz-size\"><span data-dz-size></span></div>\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\n  </div>\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n  <div class=\"dz-success-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Check</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n      </g>\n    </svg>\n  </div>\n  <div class=\"dz-error-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Error</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n        </g>\n      </g>\n    </svg>\n  </div>\n</div>",
40170
40171        // END OPTIONS
40172        // (Required by the dropzone documentation parser)
40173
40174
40175        /*
40176         Those functions register themselves to the events on init and handle all
40177         the user interface specific stuff. Overwriting them won't break the upload
40178         but can break the way it's displayed.
40179         You can overwrite them if you don't like the default behavior. If you just
40180         want to add an additional event handler, register it on the dropzone object
40181         and don't overwrite those options.
40182         */
40183
40184        // Those are self explanatory and simply concern the DragnDrop.
40185        drop: function drop(e) {
40186          return this.element.classList.remove("dz-drag-hover");
40187        },
40188        dragstart: function dragstart(e) {},
40189        dragend: function dragend(e) {
40190          return this.element.classList.remove("dz-drag-hover");
40191        },
40192        dragenter: function dragenter(e) {
40193          return this.element.classList.add("dz-drag-hover");
40194        },
40195        dragover: function dragover(e) {
40196          return this.element.classList.add("dz-drag-hover");
40197        },
40198        dragleave: function dragleave(e) {
40199          return this.element.classList.remove("dz-drag-hover");
40200        },
40201        paste: function paste(e) {},
40202
40203
40204        // Called whenever there are no files left in the dropzone anymore, and the
40205        // dropzone should be displayed as if in the initial state.
40206        reset: function reset() {
40207          return this.element.classList.remove("dz-started");
40208        },
40209
40210
40211        // Called when a file is added to the queue
40212        // Receives `file`
40213        addedfile: function addedfile(file) {
40214          var _this2 = this;
40215
40216          if (this.element === this.previewsContainer) {
40217            this.element.classList.add("dz-started");
40218          }
40219
40220          if (this.previewsContainer) {
40221            file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
40222            file.previewTemplate = file.previewElement; // Backwards compatibility
40223
40224            this.previewsContainer.appendChild(file.previewElement);
40225            for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
40226              var _ref3;
40227
40228              if (_isArray3) {
40229                if (_i3 >= _iterator3.length) break;
40230                _ref3 = _iterator3[_i3++];
40231              } else {
40232                _i3 = _iterator3.next();
40233                if (_i3.done) break;
40234                _ref3 = _i3.value;
40235              }
40236
40237              var node = _ref3;
40238
40239              node.textContent = file.name;
40240            }
40241            for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
40242              if (_isArray4) {
40243                if (_i4 >= _iterator4.length) break;
40244                node = _iterator4[_i4++];
40245              } else {
40246                _i4 = _iterator4.next();
40247                if (_i4.done) break;
40248                node = _i4.value;
40249              }
40250
40251              node.innerHTML = this.filesize(file.size);
40252            }
40253
40254            if (this.options.addRemoveLinks) {
40255              file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
40256              file.previewElement.appendChild(file._removeLink);
40257            }
40258
40259            var removeFileEvent = function removeFileEvent(e) {
40260              e.preventDefault();
40261              e.stopPropagation();
40262              if (file.status === Dropzone.UPLOADING) {
40263                return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {
40264                  return _this2.removeFile(file);
40265                });
40266              } else {
40267                if (_this2.options.dictRemoveFileConfirmation) {
40268                  return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {
40269                    return _this2.removeFile(file);
40270                  });
40271                } else {
40272                  return _this2.removeFile(file);
40273                }
40274              }
40275            };
40276
40277            for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
40278              var _ref4;
40279
40280              if (_isArray5) {
40281                if (_i5 >= _iterator5.length) break;
40282                _ref4 = _iterator5[_i5++];
40283              } else {
40284                _i5 = _iterator5.next();
40285                if (_i5.done) break;
40286                _ref4 = _i5.value;
40287              }
40288
40289              var removeLink = _ref4;
40290
40291              removeLink.addEventListener("click", removeFileEvent);
40292            }
40293          }
40294        },
40295
40296
40297        // Called whenever a file is removed.
40298        removedfile: function removedfile(file) {
40299          if (file.previewElement != null && file.previewElement.parentNode != null) {
40300            file.previewElement.parentNode.removeChild(file.previewElement);
40301          }
40302          return this._updateMaxFilesReachedClass();
40303        },
40304
40305
40306        // Called when a thumbnail has been generated
40307        // Receives `file` and `dataUrl`
40308        thumbnail: function thumbnail(file, dataUrl) {
40309          if (file.previewElement) {
40310            file.previewElement.classList.remove("dz-file-preview");
40311            for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
40312              var _ref5;
40313
40314              if (_isArray6) {
40315                if (_i6 >= _iterator6.length) break;
40316                _ref5 = _iterator6[_i6++];
40317              } else {
40318                _i6 = _iterator6.next();
40319                if (_i6.done) break;
40320                _ref5 = _i6.value;
40321              }
40322
40323              var thumbnailElement = _ref5;
40324
40325              thumbnailElement.alt = file.name;
40326              thumbnailElement.src = dataUrl;
40327            }
40328
40329            return setTimeout(function () {
40330              return file.previewElement.classList.add("dz-image-preview");
40331            }, 1);
40332          }
40333        },
40334
40335
40336        // Called whenever an error occurs
40337        // Receives `file` and `message`
40338        error: function error(file, message) {
40339          if (file.previewElement) {
40340            file.previewElement.classList.add("dz-error");
40341            if (typeof message !== "String" && message.error) {
40342              message = message.error;
40343            }
40344            for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
40345              var _ref6;
40346
40347              if (_isArray7) {
40348                if (_i7 >= _iterator7.length) break;
40349                _ref6 = _iterator7[_i7++];
40350              } else {
40351                _i7 = _iterator7.next();
40352                if (_i7.done) break;
40353                _ref6 = _i7.value;
40354              }
40355
40356              var node = _ref6;
40357
40358              node.textContent = message;
40359            }
40360          }
40361        },
40362        errormultiple: function errormultiple() {},
40363
40364
40365        // Called when a file gets processed. Since there is a cue, not all added
40366        // files are processed immediately.
40367        // Receives `file`
40368        processing: function processing(file) {
40369          if (file.previewElement) {
40370            file.previewElement.classList.add("dz-processing");
40371            if (file._removeLink) {
40372              return file._removeLink.innerHTML = this.options.dictCancelUpload;
40373            }
40374          }
40375        },
40376        processingmultiple: function processingmultiple() {},
40377
40378
40379        // Called whenever the upload progress gets updated.
40380        // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.
40381        // To get the total number of bytes of the file, use `file.size`
40382        uploadprogress: function uploadprogress(file, progress, bytesSent) {
40383          if (file.previewElement) {
40384            for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
40385              var _ref7;
40386
40387              if (_isArray8) {
40388                if (_i8 >= _iterator8.length) break;
40389                _ref7 = _iterator8[_i8++];
40390              } else {
40391                _i8 = _iterator8.next();
40392                if (_i8.done) break;
40393                _ref7 = _i8.value;
40394              }
40395
40396              var node = _ref7;
40397
40398              node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + "%";
40399            }
40400          }
40401        },
40402
40403
40404        // Called whenever the total upload progress gets updated.
40405        // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent
40406        totaluploadprogress: function totaluploadprogress() {},
40407
40408
40409        // Called just before the file is sent. Get
40409s the `xhr` object as second
40410        // parameter, so you can modify it (for example to add a CSRF token) and a
40411        // `formData` object to add additional information.
40412        sending: function sending() {},
40413        sendingmultiple: function sendingmultiple() {},
40414
40415
40416        // When the complete upload is finished and successful
40417        // Receives `file`
40418        success: function success(file) {
40419          if (file.previewElement) {
40420            return file.previewElement.classList.add("dz-success");
40421          }
40422        },
40423        successmultiple: function successmultiple() {},
40424
40425
40426        // When the upload is canceled.
40427        canceled: function canceled(file) {
40428          return this.emit("error", file, this.options.dictUploadCanceled);
40429        },
40430        canceledmultiple: function canceledmultiple() {},
40431
40432
40433        // When the upload is finished, either with success or an error.
40434        // Receives `file`
40435        complete: function complete(file) {
40436          if (file._removeLink) {
40437            file._removeLink.innerHTML = this.options.dictRemoveFile;
40438          }
40439          if (file.previewElement) {
40440            return file.previewElement.classList.add("dz-complete");
40441          }
40442        },
40443        completemultiple: function completemultiple() {},
40444        maxfilesexceeded: function maxfilesexceeded() {},
40445        maxfilesreached: function maxfilesreached() {},
40446        queuecomplete: function queuecomplete() {},
40447        addedfiles: function addedfiles() {}
40448      };
40449
40450      this.prototype._thumbnailQueue = [];
40451      this.prototype._processingThumbnail = false;
40452    }
40453
40454    // global utility
40455
40456  }, {
40457    key: "extend",
40458    value: function extend(target) {
40459      for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
40460        objects[_key2 - 1] = arguments[_key2];
40461      }
40462
40463      for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
40464        var _ref8;
40465
40466        if (_isArray9) {
40467          if (_i9 >= _iterator9.length) break;
40468          _ref8 = _iterator9[_i9++];
40469        } else {
40470          _i9 = _iterator9.next();
40471          if (_i9.done) break;
40472          _ref8 = _i9.value;
40473        }
40474
40475        var object = _ref8;
40476
40477        for (var key in object) {
40478          var val = object[key];
40479          target[key] = val;
40480        }
40481      }
40482      return target;
40483    }
40484  }]);
40485
40486  function Dropzone(el, options) {
40487    _classCallCheck(this, Dropzone);
40488
40489    var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));
40490
40491    var fallback = void 0,
40492        left = void 0;
40493    _this.element = el;
40494    // For backwards compatibility since the version was in the prototype previously
40495    _this.version = Dropzone.version;
40496
40497    _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, "");
40498
40499    _this.clickableElements = [];
40500    _this.listeners = [];
40501    _this.files = []; // All files
40502
40503    if (typeof _this.element === "string") {
40504      _this.element = document.querySelector(_this.element);
40505    }
40506
40507    // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.
40508    if (!_this.element || _this.element.nodeType == null) {
40509      throw new Error("Invalid dropzone element.");
40510    }
40511
40512    if (_this.element.dropzone) {
40513      throw new Error("Dropzone already attached.");
40514    }
40515
40516    // Now add this dropzone to the instances.
40517    Dropzone.instances.push(_this);
40518
40519    // Put the dropzone inside the element itself.
40520    _this.element.dropzone = _this;
40521
40522    var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};
40523
40524    _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});
40525
40526    // If the browser failed, just call the fallback and leave
40527    if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {
40528      var _ret;
40529
40530      return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);
40531    }
40532
40533    // @options.url = @element.getAttribute "action" unless @options.url?
40534    if (_this.options.url == null) {
40535      _this.options.url = _this.element.getAttribute("action");
40536    }
40537
40538    if (!_this.options.url) {
40539      throw new Error("No URL provided.");
40540    }
40541
40542    if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {
40543      throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
40544    }
40545
40546    if (_this.options.uploadMultiple && _this.options.chunking) {
40547      throw new Error('You cannot set both: uploadMultiple and chunking.');
40548    }
40549
40550    // Backwards compatibility
40551    if (_this.options.acceptedMimeTypes) {
40552      _this.options.acceptedFiles = _this.options.acceptedMimeTypes;
40553      delete _this.options.acceptedMimeTypes;
40554    }
40555
40556    // Backwards compatibility
40557    if (_this.options.renameFilename != null) {
40558      _this.options.renameFile = function (file) {
40559        return _this.options.renameFilename.call(_this, file.name, file);
40560      };
40561    }
40562
40563    _this.options.method = _this.options.method.toUpperCase();
40564
40565    if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {
40566      // Remove the fallback
40567      fallback.parentNode.removeChild(fallback);
40568    }
40569
40570    // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false
40571    if (_this.options.previewsContainer !== false) {
40572      if (_this.options.previewsContainer) {
40573        _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer");
40574      } else {
40575        _this.previewsContainer = _this.element;
40576      }
40577    }
40578
40579    if (_this.options.clickable) {
40580      if (_this.options.clickable === true) {
40581        _this.clickableElements = [_this.element];
40582      } else {
40583        _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable");
40584      }
40585    }
40586
40587    _this.init();
40588    return _this;
40589  }
40590
40591  // Returns all files that have been accepted
40592
40593
40594  _createClass(Dropzone, [{
40595    key: "getAcceptedFiles",
40596    value: function getAcceptedFiles() {
40597      return this.files.filter(function (file) {
40598        return file.accepted;
40599      }).map(function (file) {
40600        return file;
40601      });
40602    }
40603
40604    // Returns all files that have been rejected
40605    // Not sure when that's going to be useful, but added for completeness.
40606
40607  }, {
40608    key: "getRejectedFiles",
40609    value: function getRejectedFiles() {
40610      return this.files.filter(function (file) {
40611        return !file.accepted;
40612      }).map(function (file) {
40613        return file;
40614      });
40615    }
40616  }, {
40617    key: "getFilesWithStatus",
40618    value: function getFilesWithStatus(status) {
40619      return this.files.filter(function (file) {
40620        return file.status === status;
40621      }).map(function (file) {
40622        return file;
40623      });
40624    }
40625
40626    // Returns all files that are in the queue
40627
40628  }, {
40629    key: "getQueuedFiles",
40630    value: function getQueuedFiles() {
40631      return this.getFilesWithStatus(Dropzone.QUEUED);
40632    }
40633  }, {
40634    key: "getUploadingFiles",
40635    value: function getUploadingFiles() {
40636      return this.getFilesWithStatus(Dropzone.UPLOADING);
40637    }
40638  }, {
40639    key: "getAddedFiles",
40640    value: function getAddedFiles() {
40641      return this.getFilesWithStatus(Dropzone.ADDED);
40642    }
40643
40644    // Files that are either queued or uploading
40645
40646  }, {
40647    key: "getActiveFiles",
40648    value: function getActiveFiles() {
40649      return this.files.filter(function (file) {
40650        return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;
40651      }).map(function (file) {
40652        return file;
40653      });
40654    }
40655
40656    // The function that gets called when Dropzone is initialized. You
40657    // can (and should) setup event listeners inside this function.
40658
40659  }, {
40660    key: "init",
40661    value: function init() {
40662      var _this3 = this;
40663
40664      // In case it isn't set already
40665      if (this.element.tagName === "form") {
40666        this.element.setAttribute("enctype", "multipart/form-data");
40667      }
40668
40669      if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
40670        this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
40671      }
40672
40673      if (this.clickableElements.length) {
40674        var setupHiddenFileInput = function setupHiddenFileInput() {
40675          if (_this3.hiddenFileInput) {
40676            _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
40677          }
40678          _this3.hiddenFileInput = document.createElement("input");
40679          _this3.hiddenFileInput.setAttribute("type", "file");
40680          if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
40681            _this3.hiddenFileInput.setAttribute("multiple", "multiple");
40682          }
40683          _this3.hiddenFileInput.className = "dz-hidden-input";
40684
40685          if (_this3.options.acceptedFiles !== null) {
40686            _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles);
40687          }
40688          if (_this3.options.capture !== null) {
40689            _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture);
40690          }
40691
40692          // Not setting `display="none"` because some browsers don't accept clicks
40693          // on elements that aren't displayed.
40694          _this3.hiddenFileInput.style.visibility = "hidden";
40695          _this3.hiddenFileInput.style.position = "absolute";
40696          _this3.hiddenFileInput.style.top = "0";
40697          _this3.hiddenFileInput.style.left = "0";
40698          _this3.hiddenFileInput.style.height = "0";
40699          _this3.hiddenFileInput.style.width = "0";
40700          Dropzone.getElement(_this3.options.hiddenInputContainer, 'hiddenInputContainer').appendChild(_this3.hiddenFileInput);
40701          return _this3.hiddenFileInput.addEventListener("change", function () {
40702            var files = _this3.hiddenFileInput.files;
40703
40704            if (files.length) {
40705              for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
40706                var _ref9;
40707
40708                if (_isArray10) {
40709                  if (_i10 >= _iterator10.length) break;
40710                  _ref9 = _iterator10[_i10++];
40711                } else {
40712                  _i10 = _iterator10.next();
40713                  if (_i10.done) break;
40714                  _ref9 = _i10.value;
40715                }
40716
40717                var file = _ref9;
40718
40719                _this3.addFile(file);
40720              }
40721            }
40722            _this3.emit("addedfiles", files);
40723            return setupHiddenFileInput();
40724          });
40725        };
40726        setupHiddenFileInput();
40727      }
40728
40729      this.URL = window.URL !== null ? window.URL : window.webkitURL;
40730
40731      // Setup all event listeners on the Dropzone object itself.
40732      // They're not in @setupEventListeners() because they shouldn't be removed
40733      // again when the dropzone gets disabled.
40734      for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {
40735        var _ref10;
40736
40737        if (_isArray11) {
40738          if (_i11 >= _iterator11.length) break;
40739          _ref10 = _iterator11[_i11++];
40740        } else {
40741          _i11 = _iterator11.next();
40742          if (_i11.done) break;
40743          _ref10 = _i11.value;
40744        }
40745
40746        var eventName = _ref10;
40747
40748        this.on(eventName, this.options[eventName]);
40749      }
40750
40751      this.on("uploadprogress", function () {
40752        return _this3.updateTotalUploadProgress();
40753      });
40754
40755      this.on("removedfile", function () {
40756        return _this3.updateTotalUploadProgress();
40757      });
40758
40759      this.on("canceled", function (file) {
40760        return _this3.emit("complete", file);
40761      });
40762
40763      // Emit a `queuecomplete` event if all files finished uploading.
40764      this.on("complete", function (file) {
40765        if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {
40766          // This needs to be deferred so that `queuecomplete` really triggers after `complete`
40767          return setTimeout(function () {
40768            return _this3.emit("queuecomplete");
40769          }, 0);
40770        }
40771      });
40772
40773      var noPropagation = function noPropagation(e) {
40774        e.stopPropagation();
40775        if (e.preventDefault) {
40776          return e.preventDefault();
40777        } else {
40778          return e.returnValue = false;
40779        }
40780      };
40781
40782      // Create the listeners
40783      this.listeners = [{
40784        element: this.element,
40785        events: {
40786          "dragstart": function dragstart(e) {
40787            return _this3.emit("dragstart", e);
40788          },
40789          "dragenter": function dragenter(e) {
40790            noPropagation(e);
40791            return _this3.emit("dragenter", e);
40792          },
40793          "dragover": function dragover(e) {
40794            // Makes it possible to drag files from chrome's download bar
40795            // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar
40796            // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)
40797            var efct = void 0;
40798            try {
40799              efct = e.dataTransfer.effectAllowed;
40800            } catch (error) {}
40801            e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
40802
40803            noPropagation(e);
40804            return _this3.emit("dragover", e);
40805          },
40806          "dragleave": function dragleave(e) {
40807            return _this3.emit("dragleave", e);
40808          },
40809          "drop": function drop(e) {
40810            noPropagation(e);
40811            return _this3.drop(e);
40812          },
40813          "dragend": function dragend(e) {
40814            return _this3.emit("dragend", e);
40815          }
40816
40817          // This is disabled right now, because the browsers don't implement it properly.
40818          // "paste": (e) =>
40819          //   noPropagation e
40820          //   @paste e
40821        } }];
40822
40823      this.clickableElements.forEach(function (clickableElement) {
40824        return _this3.listeners.push({
40825          element: clickableElement,
40826          events: {
40827            "click": function click(evt) {
40828              // Only the actual dropzone or the message element should trigger file selection
40829              if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) {
40830                _this3.hiddenFileInput.click(); // Forward the click
40831              }
40832              return true;
40833            }
40834          }
40835        });
40836      });
40837
40838      this.enable();
40839
40840      return this.options.init.call(this);
40841    }
40842
40843    // Not fully tested yet
40844
40845  }, {
40846    key: "destroy",
40847    value: function destroy() {
40848      this.disable();
40849      this.removeAllFiles(true);
40850      if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {
40851        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
40852        this.hiddenFileInput = null;
40853      }
40854      delete this.element.dropzone;
40855      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
40856    }
40857  }, {
40858    key: "updateTotalUploadProgress",
40859    value: function updateTotalUploadProgress() {
40860      var totalUploadProgress = void 0;
40861      var totalBytesSent = 0;
40862      var totalBytes = 0;
40863
40864      var activeFiles = this.getActiveFiles();
40865
40866      if (activeFiles.length) {
40867        for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {
40868          var _ref11;
40869
40870          if (_isArray12) {
40871            if (_i12 >= _iterator12.length) break;
40872            _ref11 = _iterator12[_i12++];
40873          } else {
40874            _i12 = _iterator12.next();
40875            if (_i12.done) break;
40876            _ref11 = _i12.value;
40877          }
40878
40879          var file = _ref11;
40880
40881          totalBytesSent += file.upload.bytesSent;
40882          totalBytes += file.upload.total;
40883        }
40884        totalUploadProgress = 100 * totalBytesSent / totalBytes;
40885      } else {
40886        totalUploadProgress = 100;
40887      }
40888
40889      return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
40890    }
40891
40892    // @options.paramName can be a function taking one parameter rather than a string.
40893    // A parameter name for a file is obtained simply by calling this with an index number.
40894
40895  }, {
40896    key: "_getParamName",
40897    value: function _getParamName(n) {
40898      if (typeof this.options.paramName === "function") {
40899        return this.options.paramName(n);
40900      } else {
40901        return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
40902      }
40903    }
40904
40905    // If @options.renameFile is a function,
40906    // the function will be used to rename the file.name before appending it to the formData
40907
40908  }, {
40909    key: "_renameFile",
40910    value: function _renameFile(file) {
40911      if (typeof this.options.renameFile !== "function") {
40912        return file.name;
40913      }
40914      return this.options.renameFile(file);
40915    }
40916
40917    // Returns a form that can be used as fallback if the browser does not support DragnDrop
40918    //
40919    // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
40920    // This code has to pass in IE7 :(
40921
40922  }, {
40923    key: "getFallbackForm",
40924    value: function getFallbackForm() {
40925      var existingFallback = void 0,
40926          form = void 0;
40927      if (existingFallback = this.getExistingFallback()) {
40928        return existingFallback;
40929      }
40930
40931      var fieldsString = "<div class=\"dz-fallback\">";
40932      if (this.options.dictFallbackText) {
40933        fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
40934      }
40935      fieldsString += "<input type=\"file\" name=\"" + this._getParamName(0) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : undefined) + " /><input type=\"submit\" value=\"Upload!\"></div>";
40936
40937      var fields = Dropzone.createElement(fieldsString);
40938      if (this.element.tagName !== "FORM") {
40939        form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>");
40940        form.appendChild(fields);
40941      } else {
40942        // Make sure that the enctype and method attributes are set properly
40943        this.element.setAttribute("enctype", "multipart/form-data");
40944        this.element.setAttribute("method", this.options.method);
40945      }
40946      return form != null ? form : fields;
40947    }
40948
40949    // Returns the fallback elements if they exist already
40950    //
40951    // This code has to pass in IE7 :(
40952
40953  }, {
40954    key: "getExistingFallback",
40955    value: function getExistingFallback() {
40956      var getFallback = function getFallback(elements) {
40957        for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {
40958          var _ref12;
40959
40960          if (_isArray13) {
40961            if (_i13 >= _iterator13.length) break;
40962            _ref12 = _iterator13[_i13++];
40963          } else {
40964            _i13 = _iterator13.next();
40965            if (_i13.done) break;
40966            _ref12 = _i13.value;
40967          }
40968
40969          var el = _ref12;
40970
40971          if (/(^| )fallback($| )/.test(el.className)) {
40972            return el;
40973          }
40974        }
40975      };
40976
40977      var _arr = ["div", "form"];
40978      for (var _i14 = 0; _i14 < _arr.length; _i14++) {
40979        var tagName = _arr[_i14];
40980        var fallback;
40981        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
40982          return fallback;
40983        }
40984      }
40985    }
40986
40987    // Activates all listeners stored in @listeners
40988
40989  }, {
40990    key: "setupEventListeners",
40991    value: function setupEventListeners() {
40992      return this.listeners.map(function (elementListeners) {
40993        return function () {
40994          var result = [];
40995          for (var event in elementListeners.events) {
40996            var listener = elementListeners.events[event];
40997            result.push(elementListeners.element.addEventListener(event, listener, false));
40998          }
40999          return result;
41000        }();
41001      });
41002    }
41003
41004    // Deactivates all listeners stored in @listeners
41005
41006  }, {
41007    key: "removeEventListeners",
41008    value: function removeEventListeners() {
41009      return this.listeners.map(function (elementListeners) {
41010        return function () {
41011          var result = [];
41012          for (var event in elementListeners.events) {
41013            var listener = elementListeners.events[event];
41014            result.push(elementListeners.element.removeEventListener(event, listener, false));
41015          }
41016          return result;
41017        }();
41018      });
41019    }
41020
41021    // Removes all event listeners and cancels all files in the queue or being processed.
41022
41023  }, {
41024    key: "disable",
41025    value: function disable() {
41026      var _this4 = this;
41027
41028      this.clickableElements.forEach(function (element) {
41029        return element.classList.remove("dz-clickable");
41030      });
41031      this.removeEventListeners();
41032      this.disabled = true;
41033
41034      return this.files.map(function (file) {
41035        return _this4.cancelUpload(file);
41036      });
41037    }
41038  }, {
41039    key: "enable",
41040    value: function enable() {
41041      delete this.disabled;
41042      this.clickableElements.forEach(function (element) {
41043        return element.classList.add("dz-clickable");
41044      });
41045      return this.setupEventListeners();
41046    }
41047
41048    // Returns a nicely formatted filesize
41049
41050  }, {
41051    key: "filesize",
41052    value: function filesize(size) {
41053      var selectedSize = 0;
41054      var selectedUnit = "b";
41055
41056      if (size > 0) {
41057        var units = ['tb', 'gb', 'mb', 'kb', 'b'];
41058
41059        for (var i = 0; i < units.length; i++) {
41060          var unit = units[i];
41061          var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
41062
41063          if (size >= cutoff) {
41064            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
41065            selectedUnit = unit;
41066            break;
41067          }
41068        }
41069
41070        selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits
41071      }
41072
41073      return "<strong>" + selectedSize + "</strong> " + this.options.dictFileSizeUnits[selectedUnit];
41074    }
41075
41076    // Adds or removes the `dz-max-files-reached` class from the form.
41077
41078  }, {
41079    key: "_updateMaxFilesReachedClass",
41080    value: function _updateMaxFilesReachedClass() {
41081      if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
41082        if (this.getAcceptedFiles().length === this.options.maxFiles) {
41083          this.emit('maxfilesreached', this.files);
41084        }
41085        return this.element.classList.add("dz-max-files-reached");
41086      } else {
41087        return this.element.classList.remove("dz-max-files-reached");
41088      }
41089    }
41090  }, {
41091    key: "drop",
41092    value: function drop(e) {
41093      if (!e.dataTransfer) {
41094        return;
41095      }
41096      this.emit("drop", e);
41097
41098      // Convert the FileList to an Array
41099      // This is necessary for IE11
41100      var files = [];
41101      for (var i = 0; i < e.dataTransfer.files.length; i++) {
41102        files[i] = e.dataTransfer.files[i];
41103      }
41104
41105      this.emit("addedfiles", files);
41106
41107      // Even if it's a folder, files.length will contain the folders.
41108      if (files.length) {
41109        var items = e.dataTransfer.items;
41110
41111        if (items && items.length && items[0].webkitGetAsEntry != null) {
41112          // The browser supports dropping of folders, so handle items instead of files
41113          this._addFilesFromItems(items);
41114        } else {
41115          this.handleFiles(files);
41116        }
41117      }
41118    }
41119  }, {
41120    key: "paste",
41121    value: function paste(e) {
41122      if (__guard__(e != null ? e.clipboardData : undefined, function (x) {
41123        return x.items;
41124      }) == null) {
41125        return;
41126      }
41127
41128      this.emit("paste", e);
41129      var items = e.clipboardData.items;
41130
41131
41132      if (items.length) {
41133        return this._addFilesFromItems(items);
41134      }
41135    }
41136  }, {
41137    key: "handleFiles",
41138    value: function handleFiles(files) {
41139      for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {
41140        var _ref13;
41141
41142        if (_isArray14) {
41143          if (_i15 >= _iterator14.length) break;
41144          _ref13 = _iterator14[_i15++];
41145        } else {
41146          _i15 = _iterator14.next();
41147          if (_i15.done) break;
41148          _ref13 = _i15.value;
41149        }
41150
41151        var file = _ref13;
41152
41153        this.addFile(file);
41154      }
41155    }
41156
41157    // When a folder is dropped (or files are pasted), items must be handled
41158    // instead of files.
41159
41160  }, {
41161    key: "_addFilesFromItems",
41162    value: function _addFilesFromItems(items) {
41163      var _this5 = this;
41164
41165      return function () {
41166        var result = [];
41167        for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {
41168          var _ref14;
41169
41170          if (_isArray15) {
41171            if (_i16 >= _iterator15.length) break;
41172            _ref14 = _iterator15[_i16++];
41173          } else {
41174            _i16 = _iterator15.next();
41175            if (_i16.done) break;
41176            _ref14 = _i16.value;
41177          }
41178
41179          var item = _ref14;
41180
41181          var entry;
41182          if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {
41183            if (entry.isFile) {
41184              result.push(_this5.addFile(item.getAsFile()));
41185            } else if (entry.isDirectory) {
41186              // Append all files from that directory to files
41187              result.push(_this5._addFilesFromDirectory(entry, entry.name));
41188            } else {
41189              result.push(undefined);
41190            }
41191          } else if (item.getAsFile != null) {
41192            if (item.kind == null || item.kind === "file") {
41193              result.push(_this5.addFile(item.getAsFile()));
41194            } else {
41195              result.push(undefined);
41196            }
41197          } else {
41198            result.push(undefined);
41199          }
41200        }
41201        return result;
41202      }();
41203    }
41204
41205    // Goes through the directory, and adds each file it finds recursively
41206
41207  }, {
41208    key: "_addFilesFromDirectory",
41209    value: function _addFilesFromDirectory(directory, path) {
41210      var _this6 = this;
41211
41212      var dirReader = directory.createReader();
41213
41214      var errorHandler = function errorHandler(error) {
41215        return __guardMethod__(console, 'log', function (o) {
41216          return o.log(error);
41217        });
41218      };
41219
41220      var readEntries = function readEntries() {
41221        return dirReader.readEntries(function (entries) {
41222          if (entries.length > 0) {
41223            for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {
41224              var _ref15;
41225
41226              if (_isArray16) {
41227                if (_i17 >= _iterator16.length) break;
41228                _ref15 = _iterator16[_i17++];
41229              } else {
41230                _i17 = _iterator16.next();
41231                if (_i17.done) break;
41232                _ref15 = _i17.value;
41233              }
41234
41235              var entry = _ref15;
41236
41237              if (entry.isFile) {
41238                entry.file(function (file) {
41239                  if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
41240                    return;
41241                  }
41242                  file.fullPath = path + "/" + file.name;
41243                  return _this6.addFile(file);
41244                });
41245              } else if (entry.isDirectory) {
41246                _this6._addFilesFromDirectory(entry, path + "/" + entry.name);
41247              }
41248            }
41249
41250            // Recursively call readEntries() again, since browser only handle
41251            // the first 100 entries.
41252            // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries
41253            readEntries();
41254          }
41255          return null;
41256        }, errorHandler);
41257      };
41258
41259      return readEntries();
41260    }
41261
41262    // If `done()` is called without argument the file is accepted
41263    // If you call it with an error message, the file is rejected
41264    // (This allows for asynchronous validation)
41265    //
41266    // This function checks the filesize, and if the file.type passes the
41267    // `acceptedFiles` check.
41268
41269  }, {
41270    key: "accept",
41271    value: function accept(file, done) {
41272      if (this.options.maxFilesize && file.size > this.options.maxFilesize * 1024 * 1024) {
41273        return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
41274      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
41275        return done(this.options.dictInvalidFileType);
41276      } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
41277        done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
41278        return this.emit("maxfilesexceeded", file);
41279      } else {
41280        return this.options.accept.call(this, file, done);
41281      }
41282    }
41283  }, {
41284    key: "addFile",
41285    value: function addFile(file) {
41286      var _this7 = this;
41287
41288      file.upload = {
41289        uuid: Dropzone.uuidv4(),
41290        progress: 0,
41291        // Setting the total upload size to file.size for the beginning
41292        // It's actual different than the size to be transmitted.
41293        total: file.size,
41294        bytesSent: 0,
41295        filename: this._renameFile(file),
41296        chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),
41297        totalChunkCount: Math.ceil(file.size / this.options.chunkSize)
41298      };
41299      this.files.push(file);
41300
41301      file.status = Dropzone.ADDED;
41302
41303      this.emit("addedfile", file);
41304
41305      this._enqueueThumbnail(file);
41306
41307      return this.accept(file, function (error) {
41308        if (error) {
41309          file.accepted = false;
41310          _this7._errorProcessing([file], error); // Will set the file.status
41311        } else {
41312          file.accepted = true;
41313          if (_this7.options.autoQueue) {
41314            _this7.enqueueFile(file);
41315          } // Will set .accepted = true
41316        }
41317        return _this7._updateMaxFilesReachedClass();
41318      });
41319    }
41320
41321    // Wrapper for enqueueFile
41322
41323  }, {
41324    key: "enqueueFiles",
41325    value: function enqueueFiles(files) {
41326      for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {
41327        var _ref16;
41328
41329        if (_isArray17) {
41330          if (_i18 >= _iterator17.length) break;
41331          _ref16 = _iterator17[_i18++];
41332        } else {
41333          _i18 = _iterator17.next();
41334          if (_i18.done) break;
41335          _ref16 = _i18.value;
41336        }
41337
41338        var file = _ref16;
41339
41340        this.enqueueFile(file);
41341      }
41342      return null;
41343    }
41344  }, {
41345    key: "enqueueFile",
41346    value: function enqueueFile(file) {
41347      var _this8 = this;
41348
41349      if (file.status === Dropzone.ADDED && file.accepted === true) {
41350        file.status = Dropzone.QUEUED;
41351        if (this.options.autoProcessQueue) {
41352          return setTimeout(function () {
41353            return _this8.processQueue();
41354          }, 0); // Deferring the call
41355        }
41356      } else {
41357        throw new Error("This file can't be queued because it has already been processed or was rejected.");
41358      }
41359    }
41360  }, {
41361    key: "_enqueueThumbnail",
41362    value: function _enqueueThumbnail(file) {
41363      var _this9 = this;
41364
41365      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
41366        this._thumbnailQueue.push(file);
41367        return setTimeout(function () {
41368          return _this9._processThumbnailQueue();
41369        }, 0); // Deferring the call
41370      }
41371    }
41372  }, {
41373    key: "_processThumbnailQueue",
41374    value: function _processThumbnailQueue() {
41375      var _this10 = this;
41376
41377      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
41378        return;
41379      }
41380
41381      this._processingThumbnail = true;
41382      var file = this._thumbnailQueue.shift();
41383      return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {
41384        _this10.emit("thumbnail", file, dataUrl);
41385        _this10._processingThumbnail = false;
41386        return _this10._processThumbnailQueue();
41387      });
41388    }
41389
41390    // Can be called by the user to remove a file
41391
41392  }, {
41393    key: "removeFile",
41394    value: function removeFile(file) {
41395      if (file.status === Dropzone.UPLOADING) {
41396        this.cancelUpload(file);
41397      }
41398      this.files = without(this.files, file);
41399
41400      this.emit("removedfile", file);
41401      if (this.files.length === 0) {
41402        return this.emit("reset");
41403      }
41404    }
41405
41406    // Removes all files that aren't currently processed from the list
41407
41408  }, {
41409    key: "removeAllFiles",
41410    value: function removeAllFiles(cancelIfNecessary) {
41411      // Create a copy of files since removeFile() changes the @files array.
41412      if (cancelIfNecessary == null) {
41413        cancelIfNecessary = false;
41414      }
41415      for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {
41416        var _ref17;
41417
41418        if (_isArray18) {
41419          if (_i19 >= _iterator18.length) break;
41420          _ref17 = _iterator18[_i19++];
41421        } else {
41422          _i19 = _iterator18.next();
41423          if (_i19.done) break;
41424          _ref17 = _i19.value;
41425        }
41426
41427        var file = _ref17;
41428
41429        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
41430          this.removeFile(file);
41431        }
41432      }
41433      return null;
41434    }
41435
41436    // Resizes an image before it gets sent to the server. This function is the default behavior of
41437    // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with
41438    // the resized blob.
41439
41440  }, {
41441    key: "resizeImage",
41442    value: function resizeImage(file, width, height, resizeMethod, callback) {
41443      var _this11 = this;
41444
41445      return this.createThumbnail(file, width, height, resizeMethod, true, function (dataUrl, canvas) {
41446        if (canvas == null) {
41447          // The image has not been resized
41448          return callback(file);
41449        } else {
41450          var resizeMimeType = _this11.options.resizeMimeType;
41451
41452          if (resizeMimeType == null) {
41453            resizeMimeType = file.type;
41454          }
41455          var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);
41456          if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {
41457            // Now add the original EXIF information
41458            resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
41459          }
41460          return callback(Dropzone.dataURItoBlob(resizedDataURL));
41461        }
41462      });
41463    }
41464  }, {
41465    key: "createThumbnail",
41466    value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {
41467      var _this12 = this;
41468
41469      var fileReader = new FileReader();
41470
41471      fileReader.onload = function () {
41472
41473        file.dataURL = fileReader.result;
41474
41475        // Don't bother creating a thumbnail for SVG images since they're vector
41476        if (file.type === "image/svg+xml") {
41477          if (callback != null) {
41478            callback(fileReader.result);
41479          }
41480          return;
41481        }
41482
41483        return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
41484      };
41485
41486      return fileReader.readAsDataURL(file);
41487    }
41488  }, {
41489    key: "createThumbnailFromUrl",
41490    value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
41491      var _this13 = this;
41492
41493      // Not using `new Image` here because of a bug in latest Chrome versions.
41494      // See https://github.com/enyo/dropzone/pull/226
41495      var img = document.createElement("img");
41496
41497      if (crossOrigin) {
41498        img.crossOrigin = crossOrigin;
41499      }
41500
41501      img.onload = function () {
41502        var loadExif = function loadExif(callback) {
41503          return callback(1);
41504        };
41505        if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {
41506          loadExif = function loadExif(callback) {
41507            return EXIF.getData(img, function () {
41508              return callback(EXIF.getTag(this, 'Orientation'));
41509            });
41510          };
41511        }
41512
41513        return loadExif(function (orientation) {
41514          file.width = img.width;
41515          file.height = img.height;
41516
41517          var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);
41518
41519          var canvas = document.createElement("canvas");
41520          var ctx = canvas.getContext("2d");
41521
41522          canvas.width = resizeInfo.trgWidth;
41523          canvas.height = resizeInfo.trgHeight;
41524
41525          if (orientation > 4) {
41526            canvas.width = resizeInfo.trgHeight;
41527            canvas.height = resizeInfo.trgWidth;
41528          }
41529
41530          switch (orientation) {
41531            case 2:
41532              // horizontal flip
41533              ctx.translate(canvas.width, 0);
41534              ctx.scale(-1, 1);
41535              break;
41536            case 3:
41537              // 180° rotate left
41538              ctx.translate(canvas.width, canvas.height);
41539              ctx.rotate(Math.PI);
41540              break;
41541            case 4:
41542              // vertical flip
41543              ctx.translate(0, canvas.height);
41544              ctx.scale(1, -1);
41545              break;
41546            case 5:
41547              // vertical flip + 90 rotate right
41548              ctx.rotate(0.5 * Math.PI);
41549              ctx.scale(1, -1);
41550              break;
41551            case 6:
41552              // 90° rotate right
41553              ctx.rotate(0.5 * Math.PI);
41554              ctx.translate(0, -canvas.width);
41555              break;
41556            case 7:
41557              // horizontal flip + 90 rotate right
41558              ctx.rotate(0.5 * Math.PI);
41559              ctx.translate(canvas.height, -canvas.width);
41560              ctx.scale(-1, 1);
41561              break;
41562            case 8:
41563              // 90° rotate left
41564              ctx.rotate(-0.5 * Math.PI);
41565              ctx.translate(-canvas.height, 0);
41566              break;
41567          }
41568
41569          // This is a bugfix for iOS' scaling bug.
41570          drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
41571
41572          var thumbnail = canvas.toDataURL("image/png");
41573
41574          if (callback != null) {
41575            return callback(thumbnail, canvas);
41576          }
41577        });
41578      };
41579
41580      if (callback != null) {
41581        img.onerror = callback;
41582      }
41583
41584      return img.src = file.dataURL;
41585    }
41586
41587    // Goes through the queue and processes files if there aren't too many already.
41588
41589  }, {
41590    key: "processQueue",
41591    value: function processQueue() {
41592      var parallelUploads = this.options.parallelUploads;
41593
41594      var processingLength = this.getUploadingFiles().length;
41595      var i = processingLength;
41596
41597      // There are already at least as many files uploading than should be
41598      if (processingLength >= parallelUploads) {
41599        return;
41600      }
41601
41602      var queuedFiles = this.getQueuedFiles();
41603
41604      if (!(queuedFiles.length > 0)) {
41605        return;
41606      }
41607
41608      if (this.options.uploadMultiple) {
41609        // The files should be uploaded in one request
41610        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
41611      } else {
41612        while (i < parallelUploads) {
41613          if (!queuedFiles.length) {
41614            return;
41615          } // Nothing left to process
41616          this.processFile(queuedFiles.shift());
41617          i++;
41618        }
41619      }
41620    }
41621
41622    // Wrapper for `processFiles`
41623
41624  }, {
41625    key: "processFile",
41626    value: function processFile(file) {
41627      return this.processFiles([file]);
41628    }
41629
41630    // Loads the file, then calls finishedLoading()
41631
41632  }, {
41633    key: "processFiles",
41634    value: function processFiles(files) {
41635      for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {
41636        var _ref18;
41637
41638        if (_isArray19) {
41639          if (_i20 >= _iterator19.length) break;
41640          _ref18 = _iterator19[_i20++];
41641        } else {
41642          _i20 = _iterator19.next();
41643          if (_i20.done) break;
41644          _ref18 = _i20.value;
41645        }
41646
41647        var file = _ref18;
41648
41649        file.processing = true; // Backwards compatibility
41650        file.status = Dropzone.UPLOADING;
41651
41652        this.emit("processing", file);
41653      }
41654
41655      if (this.options.uploadMultiple) {
41656        this.emit("processingmultiple", files);
41657      }
41658
41659      return this.uploadFiles(files);
41660    }
41661  }, {
41662    key: "_getFilesWithXhr",
41663    value: function _getFilesWithXhr(xhr) {
41664      var files = void 0;
41665      return files = this.files.filter(function (file) {
41666        return file.xhr === xhr;
41667      }).map(function (file) {
41668        return file;
41669      });
41670    }
41671
41672    // Cancels the file upload and sets the status to CANCELED
41673    // **if** the file is actually being uploaded.
41674    // If it's still in the queue, the file is being removed from it and the status
41675    // set to CANCELED.
41676
41677  }, {
41678    key: "cancelUpload",
41679    value: function cancelUpload(file) {
41680      if (file.status === Dropzone.UPLOADING) {
41681        var groupedFiles = this._getFilesWithXhr(file.xhr);
41682        for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {
41683          var _ref19;
41684
41685          if (_isArray20) {
41686            if (_i21 >= _iterator20.length) break;
41687            _ref19 = _iterator20[_i21++];
41688          } else {
41689            _i21 = _iterator20.next();
41690            if (_i21.done) break;
41691            _ref19 = _i21.value;
41692          }
41693
41694          var groupedFile = _ref19;
41695
41696          groupedFile.status = Dropzone.CANCELED;
41697        }
41698        if (typeof file.xhr !== 'undefined') {
41699          file.xhr.abort();
41700        }
41701        for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {
41702          var _ref20;
41703
41704          if (_isArray21) {
41705            if (_i22 >= _iterator21.length) break;
41706            _ref20 = _iterator21[_i22++];
41707          } else {
41708            _i22 = _iterator21.next();
41709            if (_i22.done) break;
41710            _ref20 = _i22.value;
41711          }
41712
41713          var _groupedFile = _ref20;
41714
41715          this.emit("canceled", _groupedFile);
41716        }
41717        if (this.options.uploadMultiple) {
41718          this.emit("canceledmultiple", groupedFiles);
41719        }
41720      } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {
41721        file.status = Dropzone.CANCELED;
41722        this.emit("canceled", file);
41723        if (this.options.uploadMultiple) {
41724          this.emit("canceledmultiple", [file]);
41725        }
41726      }
41727
41728      if (this.options.autoProcessQueue) {
41729        return this.processQueue();
41730      }
41731    }
41732  }, {
41733    key: "resolveOption",
41734    value: function resolveOption(option) {
41735      if (typeof option === 'function') {
41736        for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
41737          args[_key3 - 1] = arguments[_key3];
41738        }
41739
41740        return option.apply(this, args);
41741      }
41742      return option;
41743    }
41744  }, {
41745    key: "uploadFile",
41746    value: function uploadFile(file) {
41747      return this.uploadFiles([file]);
41748    }
41749  }, {
41750    key: "uploadFiles",
41751    value: function uploadFiles(files) {
41752      var _this14 = this;
41753
41754      this._transformFiles(files, function (transformedFiles) {
41755        if (files[0].upload.chunked) {
41756          // This file should be sent in chunks!
41757
41758          // If the chunking option is set, we **know** that there can only be **one** file, since
41759          // uploadMultiple is not allowed with this option.
41760          var file = files[0];
41761          var transformedFile = transformedFiles[0];
41762          var startedChunkCount = 0;
41763
41764          file.upload.chunks = [];
41765
41766          var handleNextChunk = function handleNextChunk() {
41767            var chunkIndex = 0;
41768
41769            // Find the next item in file.upload.chunks that is not defined yet.
41770            while (file.upload.chunks[chunkIndex] !== undefined) {
41771              chunkIndex++;
41772            }
41773
41774            // This means, that all chunks have already been started.
41775            if (chunkIndex >= file.upload.totalChunkCount) return;
41776
41777            startedChunkCount++;
41778
41779            var start = chunkIndex * _this14.options.chunkSize;
41780            var end = Math.min(start + _this14.options.chunkSize, file.size);
41781
41782            var dataBlock = {
41783              name: _this14._getParamName(0),
41784              data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),
41785              filename: file.upload.filename,
41786              chunkIndex: chunkIndex
41787            };
41788
41789            file.upload.chunks[chunkIndex] = {
41790              file: file,
41791              index: chunkIndex,
41792              dataBlock: dataBlock, // In case we want to retry.
41793              status: Dropzone.UPLOADING,
41794              progress: 0,
41795              retries: 0 // The number of times this block has been retried.
41796            };
41797
41798            _this14._uploadData(files, [dataBlock]);
41799          };
41800
41801          file.upload.finishedChunkUpload = function (chunk) {
41802            var allFinished = true;
41803            chunk.status = Dropzone.SUCCESS;
41804
41805            // Clear the data from the chunk
41806            chunk.dataBlock = null;
41807            // Leaving this reference to xhr intact here will cause memory leaks in some browsers
41808            chunk.xhr = null;
41809
41810            for (var i = 0; i < file.upload.totalChunkCount; i++) {
41811              if (file.upload.chunks[i] === undefined) {
41812                return handleNextChunk();
41813              }
41814              if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {
41815                allFinished = false;
41816              }
41817            }
41818
41819            if (allFinished) {
41820              _this14.options.chunksUploaded(file, function () {
41821                _this14._finished(files, '', null);
41822              });
41823            }
41824          };
41825
41826          if (_this14.options.parallelChunkUploads) {
41827            for (var i = 0; i < file.upload.totalChunkCount; i++) {
41828              handleNextChunk();
41829            }
41830          } else {
41831            handleNextChunk();
41832          }
41833        } else {
41834          var dataBlocks = [];
41835          for (var _i23 = 0; _i23 < files.length; _i23++) {
41836            dataBlocks[_i23] = {
41837              name: _this14._getParamName(_i23),
41838              data: transformedFiles[_i23],
41839              filename: files[_i23].upload.filename
41840            };
41841          }
41842          _this14._uploadData(files, dataBlocks);
41843        }
41844      });
41845    }
41846
41847    /// Returns the right chunk for given file and xhr
41848
41849  }, {
41850    key: "_getChunk",
41851    value: function _getChunk(file, xhr) {
41852      for (var i = 0; i < file.upload.totalChunkCount; i++) {
41853        if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {
41854          return file.upload.chunks[i];
41855        }
41856      }
41857    }
41858
41859    // This function actually uploads the file(s) to the server.
41860    // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed
41861    // files, or individual chunks for chunked upload).
41862
41863  }, {
41864    key: "_uploadData",
41865    value: function _uploadData(files, dataBlocks) {
41866      var _this15 = this;
41867
41868      var xhr = new XMLHttpRequest();
41869
41870      // Put the xhr object in the file objects to be able to reference it later.
41871      for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {
41872        var _ref21;
41873
41874        if (_isArray22) {
41875          if (_i24 >= _iterator22.length) break;
41876          _ref21 = _iterator22[_i24++];
41877        } else {
41878          _i24 = _iterator22.next();
41879          if (_i24.done) break;
41880          _ref21 = _i24.value;
41881        }
41882
41883        var file = _ref21;
41884
41885        file.xhr = xhr;
41886      }
41887      if (files[0].upload.chunked) {
41888        // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk
41889        files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;
41890      }
41891
41892      var method = this.resolveOption(this.options.method, files);
41893      var url = this.resolveOption(this.options.url, files);
41894      xhr.open(method, url, true);
41895
41896      // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8
41897      xhr.timeout = this.resolveOption(this.options.timeout, files);
41898
41899      // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
41900      xhr.withCredentials = !!this.options.withCredentials;
41901
41902      xhr.onload = function (e) {
41903        _this15._finishedUploading(files, xhr, e);
41904      };
41905
41906      xhr.onerror = function () {
41907        _this15._handleUploadError(files, xhr);
41908      };
41909
41910      // Some browsers do not have the .upload property
41911      var progressObj = xhr.upload != null ? xhr.upload : xhr;
41912      progressObj.onprogress = function (e) {
41913        return _this15._updateFilesUploadProgress(files, xhr, e);
41914      };
41915
41916      var headers = {
41917        "Accept": "application/json",
41918        "Cache-Control": "no-cache",
41919        "X-Requested-With": "XMLHttpRequest"
41920      };
41921
41922      if (this.options.headers) {
41923        Dropzone.extend(headers, this.options.headers);
41924      }
41925
41926      for (var headerName in headers) {
41927        var headerValue = headers[headerName];
41928        if (headerValue) {
41929          xhr.setRequestHeader(headerName, headerValue);
41930        }
41931      }
41932
41933      var formData = new FormData();
41934
41935      // Adding all @options parameters
41936      if (this.options.params) {
41937        var additionalParams = this.options.params;
41938        if (typeof additionalParams === 'function') {
41939          additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);
41940        }
41941
41942        for (var key in additionalParams) {
41943          var value = additionalParams[key];
41944          formData.append(key, value);
41945        }
41946      }
41947
41948      // Let the user add additional data if necessary
41949      for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {
41950        var _ref22;
41951
41952        if (_isArray23) {
41953          if (_i25 >= _iterator23.length) break;
41954          _ref22 = _iterator23[_i25++];
41955        } else {
41956          _i25 = _iterator23.next();
41957          if (_i25.done) break;
41958          _ref22 = _i25.value;
41959        }
41960
41961        var _file = _ref22;
41962
41963        this.emit("sending", _file, xhr, formData);
41964      }
41965      if (this.options.uploadMultiple) {
41966        this.emit("sendingmultiple", files, xhr, formData);
41967      }
41968
41969      this._addFormElementData(formData);
41970
41971      // Finally add the files
41972      // Has to be last because some servers (eg: S3) expect the file to be the last parameter
41973      for (var i = 0; i < dataBlocks.length; i++) {
41974        var dataBlock = dataBlocks[i];
41975        formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
41976      }
41977
41978      this.submitRequest(xhr, formData, files);
41979    }
41980
41981    // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.
41982
41983  }, {
41984    key: "_transformFiles",
41985    value: function _transformFiles(files, done) {
41986      var _this16 = this;
41987
41988      var transformedFiles = [];
41989      // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.
41990      var doneCounter = 0;
41991
41992      var _loop = function _loop(i) {
41993        _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {
41994          transformedFiles[i] = transformedFile;
41995          if (++doneCounter === files.length) {
41996            done(transformedFiles);
41997          }
41998        });
41999      };
42000
42001      for (var i = 0; i < files.length; i++) {
42002        _loop(i);
42003      }
42004    }
42005
42006    // Takes care of adding other input elements of the form to the AJAX request
42007
42008  }, {
42009    key: "_addFormElementData",
42010    value: function _addFormElementData(formData) {
42011      // Take care of other input elements
42012      if (this.element.tagName === "FORM") {
42013        for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {
42014          var _ref23;
42015
42016          if (_isArray24) {
42017            if (_i26 >= _iterator24.length) break;
42018            _ref23 = _iterator24[_i26++];
42019          } else {
42020            _i26 = _iterator24.next();
42021            if (_i26.done) break;
42022            _ref23 = _i26.value;
42023          }
42024
42025          var input = _ref23;
42026
42027          var inputName = input.getAttribute("name");
42028          var inputType = input.getAttribute("type");
42029          if (inputType) inputType = inputType.toLowerCase();
42030
42031          // If the input doesn't have a name, we can't use it.
42032          if (typeof inputName === 'undefined' || inputName === null) continue;
42033
42034          if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
42035            // Possibly multiple values
42036            for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {
42037              var _ref24;
42038
42039              if (_isArray25) {
42040                if (_i27 >= _iterator25.length) break;
42041                _ref24 = _iterator25[_i27++];
42042              } else {
42043                _i27 = _iterator25.next();
42044                if (_i27.done) break;
42045                _ref24 = _i27.value;
42046              }
42047
42048              var option = _ref24;
42049
42050              if (option.selected) {
42051                formData.append(inputName, option.value);
42052              }
42053            }
42054          } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) {
42055            formData.append(inputName, input.value);
42056          }
42057        }
42058      }
42059    }
42060
42061    // Invoked when there is new progress information about given files.
42062    // If e is not provided, it is assumed that the upload is finished.
42063
42064  }, {
42065    key: "_updateFilesUploadProgress",
42066    value: function _updateFilesUploadProgress(files, xhr, e) {
42067      var progress = void 0;
42068      if (typeof e !== 'undefined') {
42069        progress = 100 * e.loaded / e.total;
42070
42071        if (files[0].upload.chunked) {
42072          var file = files[0];
42073          // Since this is a chunked upload, we need to update the appropriate chunk progress.
42074          var chunk = this._getChunk(file, xhr);
42075          chunk.progress = progress;
42076          chunk.total = e.total;
42077          chunk.bytesSent = e.loaded;
42078          var fileProgress = 0,
42079              fileTotal = void 0,
42080              fileBytesSent = void 0;
42081          file.upload.progress = 0;
42082          file.upload.total = 0;
42083          file.upload.bytesSent = 0;
42084          for (var i = 0; i < file.upload.totalChunkCount; i++) {
42085            if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {
42086              file.upload.progress += file.upload.chunks[i].progress;
42087              file.upload.total += file.upload.chunks[i].total;
42088              file.upload.bytesSent += file.upload.chunks[i].bytesSent;
42089            }
42090          }
42091          file.upload.progress = file.upload.progress / file.upload.totalChunkCount;
42092        } else {
42093          for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {
42094            var _ref25;
42095
42096            if (_isArray26) {
42097              if (_i28 >= _iterator26.length) break;
42098              _ref25 = _iterator26[_i28++];
42099            } else {
42100              _i28 = _iterator26.next();
42101              if (_i28.done) break;
42102              _ref25 = _i28.value;
42103            }
42104
42105            var _file2 = _ref25;
42106
42107            _file2.upload.progress = progress;
42108            _file2.upload.total = e.total;
42109            _file2.upload.bytesSent = e.loaded;
42110          }
42111        }
42112        for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {
42113          var _ref26;
42114
42115          if (_isArray27) {
42116            if (_i29 >= _iterator27.length) break;
42117            _ref26 = _iterator27[_i29++];
42118          } else {
42119            _i29 = _iterator27.next();
42120            if (_i29.done) break;
42121            _ref26 = _i29.value;
42122          }
42123
42124          var _file3 = _ref26;
42125
42126          this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent);
42127        }
42128      } else {
42129        // Called when the file finished uploading
42130
42131        var allFilesFinished = true;
42132
42133        progress = 100;
42134
42135        for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {
42136          var _ref27;
42137
42138          if (_isArray28) {
42139            if (_i30 >= _iterator28.length) break;
42140            _ref27 = _iterator28[_i30++];
42141          } else {
42142            _i30 = _iterator28.next();
42143            if (_i30.done) break;
42144            _ref27 = _i30.value;
42145          }
42146
42147          var _file4 = _ref27;
42148
42149          if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {
42150            allFilesFinished = false;
42151          }
42152          _file4.upload.progress = progress;
42153          _file4.upload.bytesSent = _file4.upload.total;
42154        }
42155
42156        // Nothing to do, all files already at 100%
42157        if (allFilesFinished) {
42158          return;
42159        }
42160
42161        for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {
42162          var _ref28;
42163
42164          if (_isArray29) {
42165            if (_i31 >= _iterator29.length) break;
42166            _ref28 = _iterator29[_i31++];
42167          } else {
42168            _i31 = _iterator29.next();
42169            if (_i31.done) break;
42170            _ref28 = _i31.value;
42171          }
42172
42173          var _file5 = _ref28;
42174
42175          this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent);
42176        }
42177      }
42178    }
42179  }, {
42180    key: "_finishedUploading",
42181    value: function _finishedUploading(files, xhr, e) {
42182      var response = void 0;
42183
42184      if (files[0].status === Dropzone.CANCELED) {
42185        return;
42186      }
42187
42188      if (xhr.readyState !== 4) {
42189        return;
42190      }
42191
42192      if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {
42193        response = xhr.responseText;
42194
42195        if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
42196          try {
42197            response = JSON.parse(response);
42198          } catch (error) {
42199            e = error;
42200            response = "Invalid JSON response from server.";
42201          }
42202        }
42203      }
42204
42205      this._updateFilesUploadProgress(files);
42206
42207      if (!(200 <= xhr.status && xhr.status < 300)) {
42208        this._handleUploadError(files, xhr, response);
42209      } else {
42210        if (files[0].upload.chunked) {
42211          files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));
42212        } else {
42213          this._finished(files, response, e);
42214        }
42215      }
42216    }
42217  }, {
42218    key: "_handleUploadError",
42219    value: function _handleUploadError(files, xhr, response) {
42220      if (files[0].status === Dropzone.CANCELED) {
42221        return;
42222      }
42223
42224      if (files[0].upload.chunked && this.options.retryChunks) {
42225        var chunk = this._getChunk(files[0], xhr);
42226        if (chunk.retries++ < this.options.retryChunksLimit) {
42227          this._uploadData(files, [chunk.dataBlock]);
42228          return;
42229        } else {
42230          console.warn('Retried this chunk too often. Giving up.');
42231        }
42232      }
42233
42234      for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {
42235        var _ref29;
42236
42237        if (_isArray30) {
42238          if (_i32 >= _iterator30.length) break;
42239          _ref29 = _iterator30[_i32++];
42240        } else {
42241          _i32 = _iterator30.next();
42242          if (_i32.done) break;
42243          _ref29 = _i32.value;
42244        }
42245
42246        var file = _ref29;
42247
42248        this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr);
42249      }
42250    }
42251  }, {
42252    key: "submitRequest",
42253    value: function submitRequest(xhr, formData, files) {
42254      xhr.send(formData);
42255    }
42256
42257    // Called internally when processing is finished.
42258    // Individual callbacks have to be called in the appropriate sections.
42259
42260  }, {
42261    key: "_finished",
42262    value: function _finished(files, responseText, e) {
42263      for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {
42264        var _ref30;
42265
42266        if (_isArray31) {
42267          if (_i33 >= _iterator31.length) break;
42268          _ref30 = _iterator31[_i33++];
42269        } else {
42270          _i33 = _iterator31.next();
42271          if (_i33.done) break;
42272          _ref30 = _i33.value;
42273        }
42274
42275        var file = _ref30;
42276
42277        file.status = Dropzone.SUCCESS;
42278        this.emit("success", file, responseText, e);
42279        this.emit("complete", file);
42280      }
42281      if (this.options.uploadMultiple) {
42282        this.emit("successmultiple", files, responseText, e);
42283        this.emit("completemultiple", files);
42284      }
42285
42286      if (this.options.autoProcessQueue) {
42287        return this.processQueue();
42288      }
42289    }
42290
42291    // Called internally when processing is finished.
42292    // Individual callbacks have to be called in the appropriate sections.
42293
42294  }, {
42295    key: "_errorProcessing",
42296    value: function _errorProcessing(files, message, xhr) {
42297      for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {
42298        var _ref31;
42299
42300        if (_isArray32) {
42301          if (_i34 >= _iterator32.length) break;
42302          _ref31 = _iterator32[_i34++];
42303        } else {
42304          _i34 = _iterator32.next();
42305          if (_i34.done) break;
42306          _ref31 = _i34.value;
42307        }
42308
42309        var file = _ref31;
42310
42311        file.status = Dropzone.ERROR;
42312        this.emit("error", file, message, xhr);
42313        this.emit("complete", file);
42314      }
42315      if (this.options.uploadMultiple) {
42316        this.emit("errormultiple", files, message, xhr);
42317        this.emit("completemultiple", files);
42318      }
42319
42320      if (this.options.autoProcessQueue) {
42321        return this.processQueue();
42322      }
42323    }
42324  }], [{
42325    key: "uuidv4",
42326    value: function uuidv4() {
42327      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
42328        var r = Math.random() * 16 | 0,
42329            v = c === 'x' ? r : r & 0x3 | 0x8;
42330        return v.toString(16);
42331      });
42332    }
42333  }]);
42334
42335  return Dropzone;
42336}(Emitter);
42337
42338Dropzone.initClass();
42339
42340Dropzone.version = "5.5.1";
42341
42342// This is a map of options for your different dropzones. Add configurations
42343// to this object for your different dropzone elemens.
42344//
42345// Example:
42346//
42347//     Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };
42348//
42349// To disable autoDiscover for a specific element, you can set `false` as an option:
42350//
42351//     Dropzone.options.myDisabledElementId = false;
42352//
42353// And in html:
42354//
42355//     <form action="/upload" id="my-dropzone-element-id" class="dropzone"></form>
42356Dropzone.options = {};
42357
42358// Returns the options for an element or undefined if none available.
42359Dropzone.optionsForElement = function (element) {
42360  // Get the `Dropzone.options.elementId` for this element if it exists
42361  if (element.getAttribute("id")) {
42362    return Dropzone.options[camelize(element.getAttribute("id"))];
42363  } else {
42364    return undefined;
42365  }
42366};
42367
42368// Holds a list of all dropzone instances
42369Dropzone.instances = [];
42370
42371// Returns the dropzone for given element if any
42372Dropzone.forElement = function (element) {
42373  if (typeof element === "string") {
42374    element = document.querySelector(element);
42375  }
42376  if ((element != null ? element.dropzone : undefined) == null) {
42377    throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");
42378  }
42379  return element.dropzone;
42380};
42381
42382// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.
42383Dropzone.autoDiscover = true;
42384
42385// Looks for all .dropzone elements and creates a dropzone for them
42386Dropzone.discover = function () {
42387  var dropzones = void 0;
42388  if (document.querySelectorAll) {
42389    dropzones = document.querySelectorAll(".dropzone");
42390  } else {
42391    dropzones = [];
42392    // IE :(
42393    var checkElements = function checkElements(elements) {
42394      return function () {
42395        var result = [];
42396        for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {
42397          var _ref32;
42398
42399          if (_isArray33) {
42400            if (_i35 >= _iterator33.length) break;
42401            _ref32 = _iterator33[_i35++];
42402          } else {
42403            _i35 = _iterator33.next();
42404            if (_i35.done) break;
42405            _ref32 = _i35.value;
42406          }
42407
42408          var el = _ref32;
42409
42410          if (/(^| )dropzone($| )/.test(el.className)) {
42411            result.push(dropzones.push(el));
42412          } else {
42413            result.push(undefined);
42414          }
42415        }
42416        return result;
42417      }();
42418    };
42419    checkElements(document.getElementsByTagName("div"));
42420    checkElements(document.getElementsByTagName("form"));
42421  }
42422
42423  return function () {
42424    var result = [];
42425    for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {
42426      var _ref33;
42427
42428      if (_isArray34) {
42429        if (_i36 >= _iterator34.length) break;
42430        _ref33 = _iterator34[_i36++];
42431      } else {
42432        _i36 = _iterator34.next();
42433        if (_i36.done) break;
42434        _ref33 = _i36.value;
42435      }
42436
42437      var dropzone = _ref33;
42438
42439      // Create a dropzone unless auto discover has been disabled for specific element
42440      if (Dropzone.optionsForElement(dropzone) !== false) {
42441        result.push(new Dropzone(dropzone));
42442      } else {
42443        result.push(undefined);
42444      }
42445    }
42446    return result;
42447  }();
42448};
42449
42450// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,
42451// but not correctly.
42452// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.
42453// But what to do when browsers *theoretically* support an API, but crash
42454// when using it.
42455//
42456// This is a list of regular expressions tested against navigator.userAgent
42457//
42458// ** It should only be used on browser that *do* support the API, but
42459// incorrectly **
42460//
42461Dropzone.blacklistedBrowsers = [
42462// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.
42463/opera.*(Macintosh|Windows Phone).*version\/12/i];
42464
42465// Checks if the browser is supported
42466Dropzone.isBrowserSupported = function () {
42467  var capableBrowser = true;
42468
42469  if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
42470    if (!("classList" in document.createElement("a"))) {
42471      capableBrowser = false;
42472    } else {
42473      // The browser supports the API, but may be blacklisted.
42474      for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {
42475        var _ref34;
42476
42477        if (_isArray35) {
42478          if (_i37 >= _iterator35.length) break;
42479          _ref34 = _iterator35[_i37++];
42480        } else {
42481          _i37 = _iterator35.next();
42482          if (_i37.done) break;
42483          _ref34 = _i37.value;
42484        }
42485
42486        var regex = _ref34;
42487
42488        if (regex.test(navigator.userAgent)) {
42489          capableBrowser = false;
42490          continue;
42491        }
42492      }
42493    }
42494  } else {
42495    capableBrowser = false;
42496  }
42497
42498  return capableBrowser;
42499};
42500
42501Dropzone.dataURItoBlob = function (dataURI) {
42502  // convert base64 to raw binary data held in a string
42503  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
42504  var byteString = atob(dataURI.split(',')[1]);
42505
42506  // separate out the mime component
42507  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
42508
42509  // write the bytes of the string to an ArrayBuffer
42510  var ab = new ArrayBuffer(byteString.length);
42511  var ia = new Uint8Array(ab);
42512  for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
42513    ia[i] = byteString.charCodeAt(i);
42514  }
42515
42516  // write the ArrayBuffer to a blob
42517  return new Blob([ab], { type: mimeString });
42518};
42519
42520// Returns an array without the rejected item
42521var without = function without(list, rejectedItem) {
42522  return list.filter(function (item) {
42523    return item !== rejectedItem;
42524  }).map(function (item) {
42525    return item;
42526  });
42527};
42528
42529// abc-def_ghi -> abcDefGhi
42530var camelize = function camelize(str) {
42531  return str.replace(/[\-_](\w)/g, function (match) {
42532    return match.charAt(1).toUpperCase();
42533  });
42534};
42535
42536// Creates an element from string
42537Dropzone.createElement = function (string) {
42538  var div = document.createElement("div");
42539  div.innerHTML = string;
42540  return div.childNodes[0];
42541};
42542
42543// Tests if given element is inside (or simply is) the container
42544Dropzone.elementInside = function (element, container) {
42545  if (element === container) {
42546    return true;
42547  } // Coffeescript doesn't support do/while loops
42548  while (element = element.parentNode) {
42549    if (element === container) {
42550      return true;
42551    }
42552  }
42553  return false;
42554};
42555
42556Dropzone.getElement = function (el, name) {
42557  var element = void 0;
42558  if (typeof el === "string") {
42559    element = document.querySelector(el);
42560  } else if (el.nodeType != null) {
42561    element = el;
42562  }
42563  if (element == null) {
42564    throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
42565  }
42566  return element;
42567};
42568
42569Dropzone.getElements = function (els, name) {
42570  var el = void 0,
42571      elements = void 0;
42572  if (els instanceof Array) {
42573    elements = [];
42574    try {
42575      for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {
42576        if (_isArray36) {
42577          if (_i38 >= _iterator36.length) break;
42578          el = _iterator36[_i38++];
42579        } else {
42580          _i38 = _iterator36.next();
42581          if (_i38.done) break;
42582          el = _i38.value;
42583        }
42584
42585        elements.push(this.getElement(el, name));
42586      }
42587    } catch (e) {
42588      elements = null;
42589    }
42590  } else if (typeof els === "string") {
42591    elements = [];
42592    for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {
42593      if (_isArray37) {
42594        if (_i39 >= _iterator37.length) break;
42595        el = _iterator37[_i39++];
42596      } else {
42597        _i39 = _iterator37.next();
42598        if (_i39.done) break;
42599        el = _i39.value;
42600      }
42601
42602      elements.push(el);
42603    }
42604  } else if (els.nodeType != null) {
42605    elements = [els];
42606  }
42607
42608  if (elements == null || !elements.length) {
42609    throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
42610  }
42611
42612  return elements;
42613};
42614
42615// Asks the user the question and calls accepted or rejected accordingly
42616//
42617// The default implementation just uses `window.confirm` and then calls the
42618// appropriate callback.
42619Dropzone.confirm = function (question, accepted, rejected) {
42620  if (window.confirm(question)) {
42621    return accepted();
42622  } else if (rejected != null) {
42623    return rejected();
42624  }
42625};
42626
42627// Validates the mime type like this:
42628//
42629// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept
42630Dropzone.isValidFile = function (file, acceptedFiles) {
42631  if (!acceptedFiles) {
42632    return true;
42633  } // If there are no accepted mime types, it's OK
42634  acceptedFiles = acceptedFiles.split(",");
42635
42636  var mimeType = file.type;
42637  var baseMimeType = mimeType.replace(/\/.*$/, "");
42638
42639  for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {
42640    var _ref35;
42641
42642    if (_isArray38) {
42643      if (_i40 >= _iterator38.length) break;
42644      _ref35 = _iterator38[_i40++];
42645    } else {
42646      _i40 = _iterator38.next();
42647      if (_i40.done) break;
42648      _ref35 = _i40.value;
42649    }
42650
42651    var validType = _ref35;
42652
42653    validType = validType.trim();
42654    if (validType.charAt(0) === ".") {
42655      if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
42656        return true;
42657      }
42658    } else if (/\/\*$/.test(validType)) {
42659      // This is something like a image/* mime type
42660      if (baseMimeType === validType.replace(/\/.*$/, "")) {
42661        return true;
42662      }
42663    } else {
42664      if (mimeType === validType) {
42665        return true;
42666      }
42667    }
42668  }
42669
42670  return false;
42671};
42672
42673// Augment jQuery
42674if (typeof jQuery !== 'undefined' && jQuery !== null) {
42675  jQuery.fn.dropzone = function (options) {
42676    return this.each(function () {
42677      return new Dropzone(this, options);
42678    });
42679  };
42680}
42681
42682if (typeof module !== 'undefined' && module !== null) {
42683  module.exports = Dropzone;
42684} else {
42685  window.Dropzone = Dropzone;
42686}
42687
42688// Dropzone file status codes
42689Dropzone.ADDED = "added";
42690
42691Dropzone.QUEUED = "queued";
42692// For backwards compatibility. Now, if a file is accepted, it's either queued
42693// or uploading.
42694Dropzone.ACCEPTED = Dropzone.QUEUED;
42695
42696Dropzone.UPLOADING = "uploading";
42697Dropzone.PROCESSING = Dropzone.UPLOADING; // alias
42698
42699Dropzone.CANCELED = "canceled";
42700Dropzone.ERROR = "error";
42701Dropzone.SUCCESS = "success";
42702
42703/*
42704
42705 Bugfix for iOS 6 and 7
42706 Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
42707 based on the work of https://github.com/stomita/ios-imagefile-megapixel
42708
42709 */
42710
42711// Detecting vertical squash in loaded image.
42712// Fixes a bug which squash image vertically while drawing into canvas for some images.
42713// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel
42714var detectVerticalSquash = function detectVerticalSquash(img) {
42715  var iw = img.naturalWidth;
42716  var ih = img.naturalHeight;
42717  var canvas = document.createElement("canvas");
42718  canvas.width = 1;
42719  canvas.height = ih;
42720  var ctx = canvas.getContext("2d");
42721  ctx.drawImage(img, 0, 0);
42722
42723  var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),
42724      data = _ctx$getImageData.data;
42725
42726  // search image edge pixel position in case it is squashed vertically.
42727
42728
42729  var sy = 0;
42730  var ey = ih;
42731  var py = ih;
42732  while (py > sy) {
42733    var alpha = data[(py - 1) * 4 + 3];
42734
42735    if (alpha === 0) {
42736      ey = py;
42737    } else {
42738      sy = py;
42739    }
42740
42741    py = ey + sy >> 1;
42742  }
42743  var ratio = py / ih;
42744
42745  if (ratio === 0) {
42746    return 1;
42747  } else {
42748    return ratio;
42749  }
42750};
42751
42752// A replacement for context.drawImage
42753// (args are for source and destination).
42754var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
42755  var vertSquashRatio = detectVerticalSquash(img);
42756  return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
42757};
42758
42759// Based on MinifyJpeg
42760// Source: http://www.perry.cz/files/ExifRestorer.js
42761// http://elicon.blog57.fc2.com/blog-entry-206.html
42762
42763var ExifRestore = function () {
42764  function ExifRestore() {
42765    _classCallCheck(this, ExifRestore);
42766  }
42767
42768  _createClass(ExifRestore, null, [{
42769    key: "initClass",
42770    value: function initClass() {
42771      this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
42771+/=';
42772    }
42773  }, {
42774    key: "encode64",
42775    value: function encode64(input) {
42776      var output = '';
42777      var chr1 = undefined;
42778      var chr2 = undefined;
42779      var chr3 = '';
42780      var enc1 = undefined;
42781      var enc2 = undefined;
42782      var enc3 = undefined;
42783      var enc4 = '';
42784      var i = 0;
42785      while (true) {
42786        chr1 = input[i++];
42787        chr2 = input[i++];
42788        chr3 = input[i++];
42789        enc1 = chr1 >> 2;
42790        enc2 = (chr1 & 3) << 4 | chr2 >> 4;
42791        enc3 = (chr2 & 15) << 2 | chr3 >> 6;
42792        enc4 = chr3 & 63;
42793        if (isNaN(chr2)) {
42794          enc3 = enc4 = 64;
42795        } else if (isNaN(chr3)) {
42796          enc4 = 64;
42797        }
42798        output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
42799        chr1 = chr2 = chr3 = '';
42800        enc1 = enc2 = enc3 = enc4 = '';
42801        if (!(i < input.length)) {
42802          break;
42803        }
42804      }
42805      return output;
42806    }
42807  }, {
42808    key: "restore",
42809    value: function restore(origFileBase64, resizedFileBase64) {
42810      if (!origFileBase64.match('data:image/jpeg;base64,')) {
42811        return resizedFileBase64;
42812      }
42813      var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));
42814      var segments = this.slice2Segments(rawImage);
42815      var image = this.exifManipulation(resizedFileBase64, segments);
42816      return "data:image/jpeg;base64," + this.encode64(image);
42817    }
42818  }, {
42819    key: "exifManipulation",
42820    value: function exifManipulation(resizedFileBase64, segments) {
42821      var exifArray = this.getExifArray(segments);
42822      var newImageArray = this.insertExif(resizedFileBase64, exifArray);
42823      var aBuffer = new Uint8Array(newImageArray);
42824      return aBuffer;
42825    }
42826  }, {
42827    key: "getExifArray",
42828    value: function getExifArray(segments) {
42829      var seg = undefined;
42830      var x = 0;
42831      while (x < segments.length) {
42832        seg = segments[x];
42833        if (seg[0] === 255 & seg[1] === 225) {
42834          return seg;
42835        }
42836        x++;
42837      }
42838      return [];
42839    }
42840  }, {
42841    key: "insertExif",
42842    value: function insertExif(resizedFileBase64, exifArray) {
42843      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');
42844      var buf = this.decode64(imageData);
42845      var separatePoint = buf.indexOf(255, 3);
42846      var mae = buf.slice(0, separatePoint);
42847      var ato = buf.slice(separatePoint);
42848      var array = mae;
42849      array = array.concat(exifArray);
42850      array = array.concat(ato);
42851      return array;
42852    }
42853  }, {
42854    key: "slice2Segments",
42855    value: function slice2Segments(rawImageArray) {
42856      var head = 0;
42857      var segments = [];
42858      while (true) {
42859        var length;
42860        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
42861          break;
42862        }
42863        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
42864          head += 2;
42865        } else {
42866          length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
42867          var endPoint = head + length + 2;
42868          var seg = rawImageArray.slice(head, endPoint);
42869          segments.push(seg);
42870          head = endPoint;
42871        }
42872        if (head > rawImageArray.length) {
42873          break;
42874        }
42875      }
42876      return segments;
42877    }
42878  }, {
42879    key: "decode64",
42880    value: function decode64(input) {
42881      var output = '';
42882      var chr1 = undefined;
42883      var chr2 = undefined;
42884      var chr3 = '';
42885      var enc1 = undefined;
42886      var enc2 = undefined;
42887      var enc3 = undefined;
42888      var enc4 = '';
42889      var i = 0;
42890      var buf = [];
42891      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
42892      var base64test = /[^A-Za-z0-9\+\/\=]/g;
42893      if (base64test.exec(input)) {
42894        console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.');
42895      }
42896      input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
42897      while (true) {
42898        enc1 = this.KEY_STR.indexOf(input.charAt(i++));
42899        enc2 = this.KEY_STR.indexOf(input.charAt(i++));
42900        enc3 = this.KEY_STR.indexOf(input.charAt(i++));
42901        enc4 = this.KEY_STR.indexOf(input.charAt(i++));
42902        chr1 = enc1 << 2 | enc2 >> 4;
42903        chr2 = (enc2 & 15) << 4 | enc3 >> 2;
42904        chr3 = (enc3 & 3) << 6 | enc4;
42905        buf.push(chr1);
42906        if (enc3 !== 64) {
42907          buf.push(chr2);
42908        }
42909        if (enc4 !== 64) {
42910          buf.push(chr3);
42911        }
42912        chr1 = chr2 = chr3 = '';
42913        enc1 = enc2 = enc3 = enc4 = '';
42914        if (!(i < input.length)) {
42915          break;
42916        }
42917      }
42918      return buf;
42919    }
42920  }]);
42921
42922  return ExifRestore;
42923}();
42924
42925ExifRestore.initClass();
42926
42927/*
42928 * contentloaded.js
42929 *
42930 * Author: Diego Perini (diego.perini at gmail.com)
42931 * Summary: cross-browser wrapper for DOMContentLoaded
42932 * Updated: 20101020
42933 * License: MIT
42934 * Version: 1.2
42935 *
42936 * URL:
42937 * http://javascript.nwbox.com/ContentLoaded/
42938 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
42939 */
42940
42941// @win window reference
42942// @fn function reference
42943var contentLoaded = function contentLoaded(win, fn) {
42944  var done = false;
42945  var top = true;
42946  var doc = win.document;
42947  var root = doc.documentElement;
42948  var add = doc.addEventListener ? "addEventListener" : "attachEvent";
42949  var rem = doc.addEventListener ? "removeEventListener" : "detachEvent";
42950  var pre = doc.addEventListener ? "" : "on";
42951  var init = function init(e) {
42952    if (e.type === "readystatechange" && doc.readyState !== "complete") {
42953      return;
42954    }
42955    (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
42956    if (!done && (done = true)) {
42957      return fn.call(win, e.type || e);
42958    }
42959  };
42960
42961  var poll = function poll() {
42962    try {
42963      root.doScroll("left");
42964    } catch (e) {
42965      setTimeout(poll, 50);
42966      return;
42967    }
42968    return init("poll");
42969  };
42970
42971  if (doc.readyState !== "complete") {
42972    if (doc.createEventObject && root.doScroll) {
42973      try {
42974        top = !win.frameElement;
42975      } catch (error) {}
42976      if (top) {
42977        poll();
42978      }
42979    }
42980    doc[add](pre + "DOMContentLoaded", init, false);
42981    doc[add](pre + "readystatechange", init, false);
42982    return win[add](pre + "load", init, false);
42983  }
42984};
42985
42986// As a single function to be able to write tests.
42987Dropzone._autoDiscoverFunction = function () {
42988  if (Dropzone.autoDiscover) {
42989    return Dropzone.discover();
42990  }
42991};
42992contentLoaded(window, Dropzone._autoDiscoverFunction);
42993
42994function __guard__(value, transform) {
42995  return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;
42996}
42997function __guardMethod__(obj, methodName, transform) {
42998  if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
42999    return transform(obj, methodName);
43000  } else {
43001    return undefined;
43002  }
43003}
43004
43005/**
43006 * Super simple wysiwyg editor v0.8.12
43007 * https://summernote.org
43008 *
43009 * Copyright 2013- Alan Hong. and other contributors
43010 * summernote may be freely distributed under the MIT license.
43011 *
43012 * Date: 2019-05-16T08:16Z
43013 */
43014(function (global, factory) {
43015  typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
43016  typeof define === 'function' && define.amd ? define(['jquery'], factory) :
43017  (global = global || self, factory(global.jQuery));
43018}(this, function ($$1) { 'use strict';
43019
43020  $$1 = $$1 && $$1.hasOwnProperty('default') ? $$1['default'] : $$1;
43021
43022  var Renderer = /** @class */ (function () {
43023      function Renderer(markup, children, options, callback) {
43024          this.markup = markup;
43025          this.children = children;
43026          this.options = options;
43027          this.callback = callback;
43028      }
43029      Renderer.prototype.render = function ($parent) {
43030          var $node = $$1(this.markup);
43031          if (this.options && this.options.contents) {
43032              $node.html(this.options.contents);
43033          }
43034          if (this.options && this.options.className) {
43035              $node.addClass(this.options.className);
43036          }
43037          if (this.options && this.options.data) {
43038              $$1.each(this.options.data, function (k, v) {
43039                  $node.attr('data-' + k, v);
43040              });
43041          }
43042          if (this.options && this.options.click) {
43043              $node.on('click', this.options.click);
43044          }
43045          if (this.children) {
43046              var $container_1 = $node.find('.note-children-container');
43047              this.children.forEach(function (child) {
43048                  child.render($container_1.length ? $container_1 : $node);
43049              });
43050          }
43051          if (this.callback) {
43052              this.callback($node, this.options);
43053          }
43054          if (this.options && this.options.callback) {
43055              this.options.callback($node);
43056          }
43057          if ($parent) {
43058              $parent.append($node);
43059          }
43060          return $node;
43061      };
43062      return Renderer;
43063  }());
43064  var renderer = {
43065      create: function (markup, callback) {
43066          return function () {
43067              var options = typeof arguments[1] === 'object' ? arguments[1] : arguments[0];
43068              var children = Array.isArray(arguments[0]) ? arguments[0] : [];
43069              if (options && options.children) {
43070                  children = options.children;
43071              }
43072              return new Renderer(markup, children, options, callback);
43073          };
43074      }
43075  };
43076
43077  var editor = renderer.create('<div class="note-editor note-frame panel panel-default"/>');
43078  var toolbar = renderer.create('<div class="note-toolbar panel-heading" role="toolbar"></div></div>');
43079  var editingArea = renderer.create('<div class="note-editing-area"/>');
43080  var codable = renderer.create('<textarea class="note-codable" role="textbox" aria-multiline="true"/>');
43081  var editable = renderer.create('<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>');
43082  var statusbar = renderer.create([
43083      '<output class="note-status-output" aria-live="polite"/>',
43084      '<div class="note-statusbar d-flex justify-content-center" role="status">',
43085      '  <div class="note-resizebar" role="seperator" aria-orientation="horizontal" aria-label="Resize">',
43086      '    <div class="note-icon-bar"/>',
43087      '    <div class="note-icon-bar"/>',
43088      '    <div class="note-icon-bar"/>',
43089      '  </div>',
43090      '</div>',
43091  ].join(''));
43092  var airEditor = renderer.create('<div class="note-editor"/>');
43093  var airEditable = renderer.create([
43094      '<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>',
43095      '<output class="note-status-output" aria-live="polite"/>',
43096  ].join(''));
43097  var buttonGroup = renderer.create('<div class="note-btn-group btn-group">');
43098  var dropdown = renderer.create('<ul class="dropdown-menu" role="list">', function ($node, options) {
43099      var markup = Array.isArray(options.items) ? options.items.map(function (item) {
43100          var value = (typeof item === 'string') ? item : (item.value || '');
43101          var content = options.template ? options.template(item) : item;
43102          var option = (typeof item === 'object') ? item.option : undefined;
43103          var dataValue = 'data-value="' + value + '"';
43104          var dataOption = (option !== undefined) ? ' data-option="' + option + '"' : '';
43105          return '<li role="listitem" aria-label="' + value + '"><a href="#" ' + (dataValue + dataOption) + '>' + content + '</a></li>';
43106      }).join('') : options.items;
43107      $node.html(markup).attr({ 'aria-label': options.title });
43108  });
43109  var dropdownButtonContents = function (contents, options) {
43110      return contents + ' ' + icon(options.icons.caret, 'span');
43111  };
43112  var dropdownCheck = renderer.create('<ul class="dropdown-menu note-check" role="list">', function ($node, options) {
43113      var markup = Array.isArray(options.items) ? options.items.map(function (item) {
43114          var value = (typeof item === 'string') ? item : (item.value || '');
43115          var content = options.template ? options.template(item) : item;
43116          return '<li role="listitem" aria-label="' + item + '"><a href="#" data-value="' + value + '">' + icon(options.checkClassName) + ' ' + content + '</a></li>';
43117      }).join('') : options.items;
43118      $node.html(markup).attr({ 'aria-label': options.title });
43119  });
43120  var palette = renderer.create('<div class="note-color-palette"/>', function ($node, options) {
43121      var contents = [];
43122      for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) {
43123          var eventName = options.eventName;
43124          var colors = options.colors[row];
43125          var colorsName = options.colorsName[row];
43126          var buttons = [];
43127          for (var col = 0, colSize = colors.length; col < colSize; col++) {
43128              var color = colors[col];
43129              var colorName = colorsName[col];
43130              buttons.push([
43131                  '<button type="button" class="note-color-btn"',
43132                  'style="background-color:', color, '" ',
43133                  'data-event="', eventName, '" ',
43134                  'data-value="', color, '" ',
43135                  'title="', colorName, '" ',
43136                  'aria-label="', colorName, '" ',
43137                  'data-toggle="button" tabindex="-1"></button>',
43138              ].join(''));
43139          }
43140          contents.push('<div class="note-color-row">' + buttons.join('') + '</div>');
43141      }
43142      $node.html(contents.join(''));
43143      if (options.tooltip) {
43144          $node.find('.note-color-btn').tooltip({
43145              container: options.container,
43146              trigger: 'hover',
43147              placement: 'bottom'
43148          });
43149      }
43150  });
43151  var dialog = renderer.create('<div class="modal" aria-hidden="false" tabindex="-1" role="dialog"/>', function ($node, options) {
43152      if (options.fade) {
43153          $node.addClass('fade');
43154      }
43155      $node.attr({
43156          'aria-label': options.title
43157      });
43158      $node.html([
43159          '<div class="modal-dialog">',
43160          '  <div class="modal-content">',
43161          (options.title
43162              ? '    <div class="modal-header">' +
43163              '      <h4 class="modal-title">' + options.title + '</h4>' +
43164                  '      <button type="button" class="close" data-dismiss="modal" aria-label="Close" aria-hidden="true"></button>' +
43165                  '    </div>' : ''),
43166          '    <div class="modal-body">' + options.body + '</div>',
43167          (options.footer
43168              ? '    <div class="modal-footer">' + options.footer + '</div>' : ''),
43169          '  </div>',
43170          '</div>',
43171      ].join(''));
43172  });
43173  var popover = renderer.create([
43174      '<div class="note-popover popover in">',
43175      '  <div class="arrow"/>',
43176      '  <div class="popover-content note-children-container"/>',
43177      '</div>',
43178  ].join(''), function ($node, options) {
43179      var direction = typeof options.direction !== 'undefined' ? options.direction : 'bottom';
43180      $node.addClass(direction);
43181      if (options.hideArrow) {
43182          $node.find('.arrow').hide();
43183      }
43184  });
43185  var checkbox = renderer.create('<div class="checkbox"></div>', function ($node, options) {
43186      $node.html([
43187          '<label' + (options.id ? ' for="' + options.id + '"' : '') + '>',
43188          ' <input role="checkbox" type="checkbox"' + (options.id ? ' id="' + options.id + '"' : ''),
43189          (options.checked ? ' checked' : ''),
43190          ' aria-checked="' + (options.checked ? 'true' : 'false') + '"/>',
43191          (options.text ? options.text : ''),
43192          '</label>',
43193      ].join(''));
43194  });
43195  var icon = function (iconClassName, tagName) {
43196      tagName = tagName || 'i';
43197      return '<' + tagName + ' class="' + iconClassName + '"/>';
43198  };
43199  var ui = {
43200      editor: editor,
43201      toolbar: toolbar,
43202      editingArea: editingArea,
43203      codable: codable,
43204      editable: editable,
43205      statusbar: statusbar,
43206      airEditor: airEditor,
43207      airEditable: airEditable,
43208      buttonGroup: buttonGroup,
43209      dropdown: dropdown,
43210      dropdownButtonContents: dropdownButtonContents,
43211      dropdownCheck: dropdownCheck,
43212      palette: palette,
43213      dialog: dialog,
43214      popover: popover,
43215      checkbox: checkbox,
43216      icon: icon,
43217      options: {},
43218      button: function ($node, options) {
43219          return renderer.create('<button type="button" class="note-btn btn btn-default btn-sm" role="button" tabindex="-1">', function ($node, options) {
43220              if (options && options.tooltip) {
43221                  $node.attr({
43222                      title: options.tooltip,
43223                      'aria-label': options.tooltip
43224                  }).tooltip({
43225                      container: (options.container !== undefined) ? options.container : 'body',
43226                      trigger: 'hover',
43227                      placement: 'bottom'
43228                  }).on('click', function (e) {
43229                      $$1(e.currentTarget).tooltip('hide');
43230                  });
43231              }
43232          })($node, options);
43233      },
43234      toggleBtn: function ($btn, isEnable) {
43235          $btn.toggleClass('disabled', !isEnable);
43236          $btn.attr('disabled', !isEnable);
43237      },
43238      toggleBtnActive: function ($btn, isActive) {
43239          $btn.toggleClass('active', isActive);
43240      },
43241      onDialogShown: function ($dialog, handler) {
43242          $dialog.one('shown.bs.modal', handler);
43243      },
43244      onDialogHidden: function ($dialog, handler) {
43245          $dialog.one('hidden.bs.modal', handler);
43246      },
43247      showDialog: function ($dialog) {
43248          $dialog.modal('show');
43249      },
43250      hideDialog: function ($dialog) {
43251          $dialog.modal('hide');
43252      },
43253      createLayout: function ($note, options) {
43254          var $editor = (options.airMode ? ui.airEditor([
43255              ui.editingArea([
43256                  ui.airEditable(),
43257              ]),
43258          ]) : ui.editor([
43259              ui.toolbar(),
43260              ui.editingArea([
43261                  ui.codable(),
43262                  ui.editable(),
43263              ]),
43264              ui.statusbar(),
43265          ])).render();
43266          $editor.insertAfter($note);
43267          return {
43268              note: $note,
43269              editor: $editor,
43270              toolbar: $editor.find('.note-toolbar'),
43271              editingArea: $editor.find('.note-editing-area'),
43272              editable: $editor.find('.note-editable'),
43273              codable: $editor.find('.note-codable'),
43274              statusbar: $editor.find('.note-statusbar')
43275          };
43276      },
43277      removeLayout: function ($note, layoutInfo) {
43278          $note.html(layoutInfo.editable.html());
43279          layoutInfo.editor.remove();
43280          $note.show();
43281      }
43282  };
43283
43284  $$1.summernote = $$1.summernote || {
43285      lang: {}
43286  };
43287  $$1.extend($$1.summernote.lang, {
43288      'en-US': {
43289          font: {
43290              bold: 'Bold',
43291              italic: 'Italic',
43292              underline: 'Underline',
43293              clear: 'Remove Font Style',
43294              height: 'Line Height',
43295              name: 'Font Family',
43296              strikethrough: 'Strikethrough',
43297              subscript: 'Subscript',
43298              superscript: 'Superscript',
43299              size: 'Font Size'
43300          },
43301          image: {
43302              image: 'Picture',
43303              insert: 'Insert Image',
43304              resizeFull: 'Resize full',
43305              resizeHalf: 'Resize half',
43306              resizeQuarter: 'Resize quarter',
43307              resizeNone: 'Original size',
43308              floatLeft: 'Float Left',
43309              floatRight: 'Float Right',
43310              floatNone: 'Remove float',
43311              shapeRounded: 'Shape: Rounded',
43312              shapeCircle: 'Shape: Circle',
43313              shapeThumbnail: 'Shape: Thumbnail',
43314              shapeNone: 'Shape: None',
43315              dragImageHere: 'Drag image or text here',
43316              dropImage: 'Drop image or Text',
43317              selectFromFiles: 'Select from files',
43318              maximumFileSize: 'Maximum file size',
43319              maximumFileSizeError: 'Maximum file size exceeded.',
43320              url: 'Image URL',
43321              remove: 'Remove Image',
43322              original: 'Original'
43323          },
43324          video: {
43325              video: 'Video',
43326              videoLink: 'Video Link',
43327              insert: 'Insert Video',
43328              url: 'Video URL',
43329              providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)'
43330          },
43331          link: {
43332              link: 'Link',
43333              insert: 'Insert Link',
43334              unlink: 'Unlink',
43335              edit: 'Edit',
43336              textToDisplay: 'Text to display',
43337              url: 'To what URL should this link go?',
43338              openInNewWindow: 'Open in new window'
43339          },
43340          table: {
43341              table: 'Table',
43342              addRowAbove: 'Add row above',
43343              addRowBelow: 'Add row below',
43344              addColLeft: 'Add column left',
43345              addColRight: 'Add column right',
43346              delRow: 'Delete row',
43347              delCol: 'Delete column',
43348              delTable: 'Delete table'
43349          },
43350          hr: {
43351              insert: 'Insert Horizontal Rule'
43352          },
43353          style: {
43354              style: 'Style',
43355              p: 'Normal',
43356              blockquote: 'Quote',
43357              pre: 'Code',
43358              h1: 'Header 1',
43359              h2: 'Header 2',
43360              h3: 'Header 3',
43361              h4: 'Header 4',
43362              h5: 'Header 5',
43363              h6: 'Header 6'
43364          },
43365          lists: {
43366              unordered: 'Unordered list',
43367              ordered: 'Ordered list'
43368          },
43369          options: {
43370              help: 'Help',
43371              fullscreen: 'Full Screen',
43372              codeview: 'Code View'
43373          },
43374          paragraph: {
43375              paragraph: 'Paragraph',
43376              outdent: 'Outdent',
43377              indent: 'Indent',
43378              left: 'Align left',
43379              center: 'Align center',
43380              right: 'Align right',
43381              justify: 'Justify full'
43382          },
43383          color: {
43384              recent: 'Recent Color',
43385              more: 'More Color',
43386              background: 'Background Color',
43387              foreground: 'Foreground Color',
43388              transparent: 'Transparent',
43389              setTransparent: 'Set transparent',
43390              reset: 'Reset',
43391              resetToDefault: 'Reset to default',
43392              cpSelect: 'Select'
43393          },
43394          shortcut: {
43395              shortcuts: 'Keyboard shortcuts',
43396              close: 'Close',
43397              textFormatting: 'Text formatting',
43398              action: 'Action',
43399              paragraphFormatting: 'Paragraph formatting',
43400              documentStyle: 'Document Style',
43401              extraKeys: 'Extra keys'
43402          },
43403          help: {
43404              'insertParagraph': 'Insert Paragraph',
43405              'undo': 'Undoes the last command',
43406              'redo': 'Redoes the last command',
43407              'tab': 'Tab',
43408              'untab': 'Untab',
43409              'bold': 'Set a bold style',
43410              'italic': 'Set a italic style',
43411              'underline': 'Set a underline style',
43412              'strikethrough': 'Set a strikethrough style',
43413              'removeFormat': 'Clean a style',
43414              'justifyLeft': 'Set left align',
43415              'justifyCenter': 'Set center align',
43416              'justifyRight': 'Set right align',
43417              'justifyFull': 'Set full align',
43418              'insertUnorderedList': 'Toggle unordered list',
43419              'insertOrderedList': 'Toggle ordered list',
43420              'outdent': 'Outdent on current paragraph',
43421              'indent': 'Indent on current paragraph',
43422              'formatPara': 'Change current block\'s format as a paragraph(P tag)',
43423              'formatH1': 'Change current block\'s format as H1',
43424              'formatH2': 'Change current block\'s format as H2',
43425              'formatH3': 'Change current block\'s format as H3',
43426              'formatH4': 'Change current block\'s format as H4',
43427              'formatH5': 'Change current block\'s format as H5',
43428              'formatH6': 'Change current block\'s format as H6',
43429              'insertHorizontalRule': 'Insert horizontal rule',
43430              'linkDialog.show': 'Show Link Dialog'
43431          },
43432          history: {
43433              undo: 'Undo',
43434              redo: 'Redo'
43435          },
43436          specialChar: {
43437              specialChar: 'SPECIAL CHARACTERS',
43438              select: 'Select Special characters'
43439          }
43440      }
43441  });
43442
43443  var isSupportAmd = typeof define === 'function' && define.amd; // eslint-disable-line
43444  /**
43445   * returns whether font is installed or not.
43446   *
43447   * @param {String} fontName
43448   * @return {Boolean}
43449   */
43450  function isFontInstalled(fontName) {
43451      var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS';
43452      var testText = 'mmmmmmmmmmwwwww';
43453      var testSize = '200px';
43454      var canvas = document.createElement('canvas');
43455      var context = canvas.getContext('2d');
43456      context.font = testSize + " '" + testFontName + "'";
43457      var originalWidth = context.measureText(testText).width;
43458      context.font = testSize + " '" + fontName + "', '" + testFontName + "'";
43459      var width = context.measureText(testText).width;
43460      return originalWidth !== width;
43461  }
43462  var userAgent = navigator.userAgent;
43463  var isMSIE = /MSIE|Trident/i.test(userAgent);
43464  var browserVersion;
43465  if (isMSIE) {
43466      var matches = /MSIE (\d+[.]\d+)/.exec(userAgent);
43467      if (matches) {
43468          browserVersion = parseFloat(matches[1]);
43469      }
43470      matches = /Trident\/.*rv:([0-9]{1,}[.0-9]{0,})/.exec(userAgent);
43471      if (matches) {
43472          browserVersion = parseFloat(matches[1]);
43473      }
43474  }
43475  var isEdge = /Edge\/\d+/.test(userAgent);
43476  var hasCodeMirror = !!window.CodeMirror;
43477  var isSupportTouch = (('ontouchstart' in window) ||
43478      (navigator.MaxTouchPoints > 0) ||
43479      (navigator.msMaxTouchPoints > 0));
43480  // [workaround] IE doesn't have input events for contentEditable
43481  // - see: https://goo.gl/4bfIvA
43482  var inputEventName = (isMSIE || isEdge) ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';
43483  /**
43484   * @class core.env
43485   *
43486   * Object which check platform and agent
43487   *
43488   * @singleton
43489   * @alternateClassName env
43490   */
43491  var env = {
43492      isMac: navigator.appVersion.indexOf('Mac') > -1,
43493      isMSIE: isMSIE,
43494      isEdge: isEdge,
43495      isFF: !isEdge && /firefox/i.test(userAgent),
43496      isPhantom: /PhantomJS/i.test(userAgent),
43497      isWebkit: !isEdge && /webkit/i.test(userAgent),
43498      isChrome: !isEdge && /chrome/i.test(userAgent),
43499      isSafari: !isEdge && /safari/i.test(userAgent),
43500      browserVersion: browserVersion,
43501      jqueryVersion: parseFloat($$1.fn.jquery),
43502      isSupportAmd: isSupportAmd,
vendor: 37,811 bytes, lines 43503-44904
43503      isSupportTouch: isSupportTouch,
43504      hasCodeMirror: hasCodeMirror,
43505      isFontInstalled: isFontInstalled,
43506      isW3CRangeSupport: !!document.createRange,
43507      inputEventName: inputEventName
43508  };
43509
43510  /**
43511   * @class core.func
43512   *
43513   * func utils (for high-order func's arg)
43514   *
43515   * @singleton
43516   * @alternateClassName func
43517   */
43518  function eq(itemA) {
43519      return function (itemB) {
43520          return itemA === itemB;
43521      };
43522  }
43523  function eq2(itemA, itemB) {
43524      return itemA === itemB;
43525  }
43526  function peq2(propName) {
43527      return function (itemA, itemB) {
43528          return itemA[propName] === itemB[propName];
43529      };
43530  }
43531  function ok() {
43532      return true;
43533  }
43534  function fail() {
43535      return false;
43536  }
43537  function not(f) {
43538      return function () {
43539          return !f.apply(f, arguments);
43540      };
43541  }
43542  function and(fA, fB) {
43543      return function (item) {
43544          return fA(item) && fB(item);
43545      };
43546  }
43547  function self(a) {
43548      return a;
43549  }
43550  function invoke(obj, method) {
43551      return function () {
43552          return obj[method].apply(obj, arguments);
43553      };
43554  }
43555  var idCounter = 0;
43556  /**
43557   * generate a globally-unique id
43558   *
43559   * @param {String} [prefix]
43560   */
43561  function uniqueId(prefix) {
43562      var id = ++idCounter + '';
43563      return prefix ? prefix + id : id;
43564  }
43565  /**
43566   * returns bnd (bounds) from rect
43567   *
43568   * - IE Compatibility Issue: http://goo.gl/sRLOAo
43569   * - Scroll Issue: http://goo.gl/sNjUc
43570   *
43571   * @param {Rect} rect
43572   * @return {Object} bounds
43573   * @return {Number} bounds.top
43574   * @return {Number} bounds.left
43575   * @return {Number} bounds.width
43576   * @return {Number} bounds.height
43577   */
43578  function rect2bnd(rect) {
43579      var $document = $(document);
43580      return {
43581          top: rect.top + $document.scrollTop(),
43582          left: rect.left + $document.scrollLeft(),
43583          width: rect.right - rect.left,
43584          height: rect.bottom - rect.top
43585      };
43586  }
43587  /**
43588   * returns a copy of the object where the keys have become the values and the values the keys.
43589   * @param {Object} obj
43590   * @return {Object}
43591   */
43592  function invertObject(obj) {
43593      var inverted = {};
43594      for (var key in obj) {
43595          if (obj.hasOwnProperty(key)) {
43596              inverted[obj[key]] = key;
43597          }
43598      }
43599      return inverted;
43600  }
43601  /**
43602   * @param {String} namespace
43603   * @param {String} [prefix]
43604   * @return {String}
43605   */
43606  function namespaceToCamel(namespace, prefix) {
43607      prefix = prefix || '';
43608      return prefix + namespace.split('.').map(function (name) {
43609          return name.substring(0, 1).toUpperCase() + name.substring(1);
43610      }).join('');
43611  }
43612  /**
43613   * Returns a function, that, as long as it continues to be invoked, will not
43614   * be triggered. The function will be called after it stops being called for
43615   * N milliseconds. If `immediate` is passed, trigger the function on the
43616   * leading edge, instead of the trailing.
43617   * @param {Function} func
43618   * @param {Number} wait
43619   * @param {Boolean} immediate
43620   * @return {Function}
43621   */
43622  function debounce(func, wait, immediate) {
43623      var timeout;
43624      return function () {
43625          var context = this;
43626          var args = arguments;
43627          var later = function () {
43628              timeout = null;
43629              if (!immediate) {
43630                  func.apply(context, args);
43631              }
43632          };
43633          var callNow = immediate && !timeout;
43634          clearTimeout(timeout);
43635          timeout = setTimeout(later, wait);
43636          if (callNow) {
43637              func.apply(context, args);
43638          }
43639      };
43640  }
43641  /**
43642   *
43643   * @param {String} url
43644   * @return {Boolean}
43645   */
43646  function isValidUrl(url) {
43647      var expression = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/gi;
43648      return expression.test(url);
43649  }
43650  var func = {
43651      eq: eq,
43652      eq2: eq2,
43653      peq2: peq2,
43654      ok: ok,
43655      fail: fail,
43656      self: self,
43657      not: not,
43658      and: and,
43659      invoke: invoke,
43660      uniqueId: uniqueId,
43661      rect2bnd: rect2bnd,
43662      invertObject: invertObject,
43663      namespaceToCamel: namespaceToCamel,
43664      debounce: debounce,
43665      isValidUrl: isValidUrl
43666  };
43667
43668  /**
43669   * returns the first item of an array.
43670   *
43671   * @param {Array} array
43672   */
43673  function head(array) {
43674      return array[0];
43675  }
43676  /**
43677   * returns the last item of an array.
43678   *
43679   * @param {Array} array
43680   */
43681  function last(array) {
43682      return array[array.length - 1];
43683  }
43684  /**
43685   * returns everything but the last entry of the array.
43686   *
43687   * @param {Array} array
43688   */
43689  function initial(array) {
43690      return array.slice(0, array.length - 1);
43691  }
43692  /**
43693   * returns the rest of the items in an array.
43694   *
43695   * @param {Array} array
43696   */
43697  function tail(array) {
43698      return array.slice(1);
43699  }
43700  /**
43701   * returns item of array
43702   */
43703  function find(array, pred) {
43704      for (var idx = 0, len = array.length; idx < len; idx++) {
43705          var item = array[idx];
43706          if (pred(item)) {
43707              return item;
43708          }
43709      }
43710  }
43711  /**
43712   * returns true if all of the values in the array pass the predicate truth test.
43713   */
43714  function all(array, pred) {
43715      for (var idx = 0, len = array.length; idx < len; idx++) {
43716          if (!pred(array[idx])) {
43717              return false;
43718          }
43719      }
43720      return true;
43721  }
43722  /**
43723   * returns true if the value is present in the list.
43724   */
43725  function contains(array, item) {
43726      if (array && array.length && item) {
43727          return array.indexOf(item) !== -1;
43728      }
43729      return false;
43730  }
43731  /**
43732   * get sum from a list
43733   *
43734   * @param {Array} array - array
43735   * @param {Function} fn - iterator
43736   */
43737  function sum(array, fn) {
43738      fn = fn || func.self;
43739      return array.reduce(function (memo, v) {
43740          return memo + fn(v);
43741      }, 0);
43742  }
43743  /**
43744   * returns a copy of the collection with array type.
43745   * @param {Collection} collection - collection eg) node.childNodes, ...
43746   */
43747  function from(collection) {
43748      var result = [];
43749      var length = collection.length;
43750      var idx = -1;
43751      while (++idx < length) {
43752          result[idx] = collection[idx];
43753      }
43754      return result;
43755  }
43756  /**
43757   * returns whether list is empty or not
43758   */
43759  function isEmpty(array) {
43760      return !array || !array.length;
43761  }
43762  /**
43763   * cluster elements by predicate function.
43764   *
43765   * @param {Array} array - array
43766   * @param {Function} fn - predicate function for cluster rule
43767   * @param {Array[]}
43768   */
43769  function clusterBy(array, fn) {
43770      if (!array.length) {
43771          return [];
43772      }
43773      var aTail = tail(array);
43774      return aTail.reduce(function (memo, v) {
43775          var aLast = last(memo);
43776          if (fn(last(aLast), v)) {
43777              aLast[aLast.length] = v;
43778          }
43779          else {
43780              memo[memo.length] = [v];
43781          }
43782          return memo;
43783      }, [[head(array)]]);
43784  }
43785  /**
43786   * returns a copy of the array with all false values removed
43787   *
43788   * @param {Array} array - array
43789   * @param {Function} fn - predicate function for cluster rule
43790   */
43791  function compact(array) {
43792      var aResult = [];
43793      for (var idx = 0, len = array.length; idx < len; idx++) {
43794          if (array[idx]) {
43795              aResult.push(array[idx]);
43796          }
43797      }
43798      return aResult;
43799  }
43800  /**
43801   * produces a duplicate-free version of the array
43802   *
43803   * @param {Array} array
43804   */
43805  function unique(array) {
43806      var results = [];
43807      for (var idx = 0, len = array.length; idx < len; idx++) {
43808          if (!contains(results, array[idx])) {
43809              results.push(array[idx]);
43810          }
43811      }
43812      return results;
43813  }
43814  /**
43815   * returns next item.
43816   * @param {Array} array
43817   */
43818  function next(array, item) {
43819      if (array && array.length && item) {
43820          var idx = array.indexOf(item);
43821          return idx === -1 ? null : array[idx + 1];
43822      }
43823      return null;
43824  }
43825  /**
43826   * returns prev item.
43827   * @param {Array} array
43828   */
43829  function prev(array, item) {
43830      if (array && array.length && item) {
43831          var idx = array.indexOf(item);
43832          return idx === -1 ? null : array[idx - 1];
43833      }
43834      return null;
43835  }
43836  /**
43837   * @class core.list
43838   *
43839   * list utils
43840   *
43841   * @singleton
43842   * @alternateClassName list
43843   */
43844  var lists = {
43845      head: head,
43846      last: last,
43847      initial: initial,
43848      tail: tail,
43849      prev: prev,
43850      next: next,
43851      find: find,
43852      contains: contains,
43853      all: all,
43854      sum: sum,
43855      from: from,
43856      isEmpty: isEmpty,
43857      clusterBy: clusterBy,
43858      compact: compact,
43859      unique: unique
43860  };
43861
43862  var NBSP_CHAR = String.fromCharCode(160);
43863  var ZERO_WIDTH_NBSP_CHAR = '\ufeff';
43864  /**
43865   * @method isEditable
43866   *
43867   * returns whether node is `note-editable` or not.
43868   *
43869   * @param {Node} node
43870   * @return {Boolean}
43871   */
43872  function isEditable(node) {
43873      return node && $$1(node).hasClass('note-editable');
43874  }
43875  /**
43876   * @method isControlSizing
43877   *
43878   * returns whether node is `note-control-sizing` or not.
43879   *
43880   * @param {Node} node
43881   * @return {Boolean}
43882   */
43883  function isControlSizing(node) {
43884      return node && $$1(node).hasClass('note-control-sizing');
43885  }
43886  /**
43887   * @method makePredByNodeName
43888   *
43889   * returns predicate which judge whether nodeName is same
43890   *
43891   * @param {String} nodeName
43892   * @return {Function}
43893   */
43894  function makePredByNodeName(nodeName) {
43895      nodeName = nodeName.toUpperCase();
43896      return function (node) {
43897          return node && node.nodeName.toUpperCase() === nodeName;
43898      };
43899  }
43900  /**
43901   * @method isText
43902   *
43903   *
43904   *
43905   * @param {Node} node
43906   * @return {Boolean} true if node's type is text(3)
43907   */
43908  function isText(node) {
43909      return node && node.nodeType === 3;
43910  }
43911  /**
43912   * @method isElement
43913   *
43914   *
43915   *
43916   * @param {Node} node
43917   * @return {Boolean} true if node's type is element(1)
43918   */
43919  function isElement(node) {
43920      return node && node.nodeType === 1;
43921  }
43922  /**
43923   * ex) br, col, embed, hr, img, input, ...
43924   * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
43925   */
43926  function isVoid(node) {
43927      return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON|^INPUT|^AUDIO|^VIDEO|^EMBED/.test(node.nodeName.toUpperCase());
43928  }
43929  function isPara(node) {
43930      if (isEditable(node)) {
43931          return false;
43932      }
43933      // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph
43934      return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());
43935  }
43936  function isHeading(node) {
43937      return node && /^H[1-7]/.test(node.nodeName.toUpperCase());
43938  }
43939  var isPre = makePredByNodeName('PRE');
43940  var isLi = makePredByNodeName('LI');
43941  function isPurePara(node) {
43942      return isPara(node) && !isLi(node);
43943  }
43944  var isTable = makePredByNodeName('TABLE');
43945  var isData = makePredByNodeName('DATA');
43946  function isInline(node) {
43947      return !isBodyContainer(node) &&
43948          !isList(node) &&
43949          !isHr(node) &&
43950          !isPara(node) &&
43951          !isTable(node) &&
43952          !isBlockquote(node) &&
43953          !isData(node);
43954  }
43955  function isList(node) {
43956      return node && /^UL|^OL/.test(node.nodeName.toUpperCase());
43957  }
43958  var isHr = makePredByNodeName('HR');
43959  function isCell(node) {
43960      return node && /^TD|^TH/.test(node.nodeName.toUpperCase());
43961  }
43962  var isBlockquote = makePredByNodeName('BLOCKQUOTE');
43963  function isBodyContainer(node) {
43964      return isCell(node) || isBlockquote(node) || isEditable(node);
43965  }
43966  var isAnchor = makePredByNodeName('A');
43967  function isParaInline(node) {
43968      return isInline(node) && !!ancestor(node, isPara);
43969  }
43970  function isBodyInline(node) {
43971      return isInline(node) && !ancestor(node, isPara);
43972  }
43973  var isBody = makePredByNodeName('BODY');
43974  /**
43975   * returns whether nodeB is closest sibling of nodeA
43976   *
43977   * @param {Node} nodeA
43978   * @param {Node} nodeB
43979   * @return {Boolean}
43980   */
43981  function isClosestSibling(nodeA, nodeB) {
43982      return nodeA.nextSibling === nodeB ||
43983          nodeA.previousSibling === nodeB;
43984  }
43985  /**
43986   * returns array of closest siblings with node
43987   *
43988   * @param {Node} node
43989   * @param {function} [pred] - predicate function
43990   * @return {Node[]}
43991   */
43992  function withClosestSiblings(node, pred) {
43993      pred = pred || func.ok;
43994      var siblings = [];
43995      if (node.previousSibling && pred(node.previousSibling)) {
43996          siblings.push(node.previousSibling);
43997      }
43998      siblings.push(node);
43999      if (node.nextSibling && pred(node.nextSibling)) {
44000          siblings.push(node.nextSibling);
44001      }
44002      return siblings;
44003  }
44004  /**
44005   * blank HTML for cursor position
44006   * - [workaround] old IE only works with &nbsp;
44007   * - [workaround] IE11 and other browser works with bogus br
44008   */
44009  var blankHTML = env.isMSIE && env.browserVersion < 11 ? '&nbsp;' : '<br>';
44010  /**
44011   * @method nodeLength
44012   *
44013   * returns #text's text size or element's childNodes size
44014   *
44015   * @param {Node} node
44016   */
44017  function nodeLength(node) {
44018      if (isText(node)) {
44019          return node.nodeValue.length;
44020      }
44021      if (node) {
44022          return node.childNodes.length;
44023      }
44024      return 0;
44025  }
44026  /**
44027   * returns whether node is empty or not.
44028   *
44029   * @param {Node} node
44030   * @return {Boolean}
44031   */
44032  function isEmpty$1(node) {
44033      var len = nodeLength(node);
44034      if (len === 0) {
44035          return true;
44036      }
44037      else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) {
44038          // ex) <p><br></p>, <span><br></span>
44039          return true;
44040      }
44041      else if (lists.all(node.childNodes, isText) && node.innerHTML === '') {
44042          // ex) <p></p>, <span></span>
44043          return true;
44044      }
44045      return false;
44046  }
44047  /**
44048   * padding blankHTML if node is empty (for cursor position)
44049   */
44050  function paddingBlankHTML(node) {
44051      if (!isVoid(node) && !nodeLength(node)) {
44052          node.innerHTML = blankHTML;
44053      }
44054  }
44055  /**
44056   * find nearest ancestor predicate hit
44057   *
44058   * @param {Node} node
44059   * @param {Function} pred - predicate function
44060   */
44061  function ancestor(node, pred) {
44062      while (node) {
44063          if (pred(node)) {
44064              return node;
44065          }
44066          if (isEditable(node)) {
44067              break;
44068          }
44069          node = node.parentNode;
44070      }
44071      return null;
44072  }
44073  /**
44074   * find nearest ancestor only single child blood line and predicate hit
44075   *
44076   * @param {Node} node
44077   * @param {Function} pred - predicate function
44078   */
44079  function singleChildAncestor(node, pred) {
44080      node = node.parentNode;
44081      while (node) {
44082          if (nodeLength(node) !== 1) {
44083              break;
44084          }
44085          if (pred(node)) {
44086              return node;
44087          }
44088          if (isEditable(node)) {
44089              break;
44090          }
44091          node = node.parentNode;
44092      }
44093      return null;
44094  }
44095  /**
44096   * returns new array of ancestor nodes (until predicate hit).
44097   *
44098   * @param {Node} node
44099   * @param {Function} [optional] pred - predicate function
44100   */
44101  function listAncestor(node, pred) {
44102      pred = pred || func.fail;
44103      var ancestors = [];
44104      ancestor(node, function (el) {
44105          if (!isEditable(el)) {
44106              ancestors.push(el);
44107          }
44108          return pred(el);
44109      });
44110      return ancestors;
44111  }
44112  /**
44113   * find farthest ancestor predicate hit
44114   */
44115  function lastAncestor(node, pred) {
44116      var ancestors = listAncestor(node);
44117      return lists.last(ancestors.filter(pred));
44118  }
44119  /**
44120   * returns common ancestor node between two nodes.
44121   *
44122   * @param {Node} nodeA
44123   * @param {Node} nodeB
44124   */
44125  function commonAncestor(nodeA, nodeB) {
44126      var ancestors = listAncestor(nodeA);
44127      for (var n = nodeB; n; n = n.parentNode) {
44128          if (ancestors.indexOf(n) > -1)
44129              return n;
44130      }
44131      return null; // difference document area
44132  }
44133  /**
44134   * listing all previous siblings (until predicate hit).
44135   *
44136   * @param {Node} node
44137   * @param {Function} [optional] pred - predicate function
44138   */
44139  function listPrev(node, pred) {
44140      pred = pred || func.fail;
44141      var nodes = [];
44142      while (node) {
44143          if (pred(node)) {
44144              break;
44145          }
44146          nodes.push(node);
44147          node = node.previousSibling;
44148      }
44149      return nodes;
44150  }
44151  /**
44152   * listing next siblings (until predicate hit).
44153   *
44154   * @param {Node} node
44155   * @param {Function} [pred] - predicate function
44156   */
44157  function listNext(node, pred) {
44158      pred = pred || func.fail;
44159      var nodes = [];
44160      while (node) {
44161          if (pred(node)) {
44162              break;
44163          }
44164          nodes.push(node);
44165          node = node.nextSibling;
44166      }
44167      return nodes;
44168  }
44169  /**
44170   * listing descendant nodes
44171   *
44172   * @param {Node} node
44173   * @param {Function} [pred] - predicate function
44174   */
44175  function listDescendant(node, pred) {
44176      var descendants = [];
44177      pred = pred || func.ok;
44178      // start DFS(depth first search) with node
44179      (function fnWalk(current) {
44180          if (node !== current && pred(current)) {
44181              descendants.push(current);
44182          }
44183          for (var idx = 0, len = current.childNodes.length; idx < len; idx++) {
44184              fnWalk(current.childNodes[idx]);
44185          }
44186      })(node);
44187      return descendants;
44188  }
44189  /**
44190   * wrap node with new tag.
44191   *
44192   * @param {Node} node
44193   * @param {Node} tagName of wrapper
44194   * @return {Node} - wrapper
44195   */
44196  function wrap(node, wrapperName) {
44197      var parent = node.parentNode;
44198      var wrapper = $$1('<' + wrapperName + '>')[0];
44199      parent.insertBefore(wrapper, node);
44200      wrapper.appendChild(node);
44201      return wrapper;
44202  }
44203  /**
44204   * insert node after preceding
44205   *
44206   * @param {Node} node
44207   * @param {Node} preceding - predicate function
44208   */
44209  function insertAfter(node, preceding) {
44210      var next = preceding.nextSibling;
44211      var parent = preceding.parentNode;
44212      if (next) {
44213          parent.insertBefore(node, next);
44214      }
44215      else {
44216          parent.appendChild(node);
44217      }
44218      return node;
44219  }
44220  /**
44221   * append elements.
44222   *
44223   * @param {Node} node
44224   * @param {Collection} aChild
44225   */
44226  function appendChildNodes(node, aChild) {
44227      $$1.each(aChild, function (idx, child) {
44228          node.appendChild(child);
44229      });
44230      return node;
44231  }
44232  /**
44233   * returns whether boundaryPoint is left edge or not.
44234   *
44235   * @param {BoundaryPoint} point
44236   * @return {Boolean}
44237   */
44238  function isLeftEdgePoint(point) {
44239      return point.offset === 0;
44240  }
44241  /**
44242   * returns whether boundaryPoint is right edge or not.
44243   *
44244   * @param {BoundaryPoint} point
44245   * @return {Boolean}
44246   */
44247  function isRightEdgePoint(point) {
44248      return point.offset === nodeLength(point.node);
44249  }
44250  /**
44251   * returns whether boundaryPoint is edge or not.
44252   *
44253   * @param {BoundaryPoint} point
44254   * @return {Boolean}
44255   */
44256  function isEdgePoint(point) {
44257      return isLeftEdgePoint(point) || isRightEdgePoint(point);
44258  }
44259  /**
44260   * returns whether node is left edge of ancestor or not.
44261   *
44262   * @param {Node} node
44263   * @param {Node} ancestor
44264   * @return {Boolean}
44265   */
44266  function isLeftEdgeOf(node, ancestor) {
44267      while (node && node !== ancestor) {
44268          if (position(node) !== 0) {
44269              return false;
44270          }
44271          node = node.parentNode;
44272      }
44273      return true;
44274  }
44275  /**
44276   * returns whether node is right edge of ancestor or not.
44277   *
44278   * @param {Node} node
44279   * @param {Node} ancestor
44280   * @return {Boolean}
44281   */
44282  function isRightEdgeOf(node, ancestor) {
44283      if (!ancestor) {
44284          return false;
44285      }
44286      while (node && node !== ancestor) {
44287          if (position(node) !== nodeLength(node.parentNode) - 1) {
44288              return false;
44289          }
44290          node = node.parentNode;
44291      }
44292      return true;
44293  }
44294  /**
44295   * returns whether point is left edge of ancestor or not.
44296   * @param {BoundaryPoint} point
44297   * @param {Node} ancestor
44298   * @return {Boolean}
44299   */
44300  function isLeftEdgePointOf(point, ancestor) {
44301      return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor);
44302  }
44303  /**
44304   * returns whether point is right edge of ancestor or not.
44305   * @param {BoundaryPoint} point
44306   * @param {Node} ancestor
44307   * @return {Boolean}
44308   */
44309  function isRightEdgePointOf(point, ancestor) {
44310      return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor);
44311  }
44312  /**
44313   * returns offset from parent.
44314   *
44315   * @param {Node} node
44316   */
44317  function position(node) {
44318      var offset = 0;
44319      while ((node = node.previousSibling)) {
44320          offset += 1;
44321      }
44322      return offset;
44323  }
44324  function hasChildren(node) {
44325      return !!(node && node.childNodes && node.childNodes.length);
44326  }
44327  /**
44328   * returns previous boundaryPoint
44329   *
44330   * @param {BoundaryPoint} point
44331   * @param {Boolean} isSkipInnerOffset
44332   * @return {BoundaryPoint}
44333   */
44334  function prevPoint(point, isSkipInnerOffset) {
44335      var node;
44336      var offset;
44337      if (point.offset === 0) {
44338          if (isEditable(point.node)) {
44339              return null;
44340          }
44341          node = point.node.parentNode;
44342          offset = position(point.node);
44343      }
44344      else if (hasChildren(point.node)) {
44345          node = point.node.childNodes[point.offset - 1];
44346          offset = nodeLength(node);
44347      }
44348      else {
44349          node = point.node;
44350          offset = isSkipInnerOffset ? 0 : point.offset - 1;
44351      }
44352      return {
44353          node: node,
44354          offset: offset
44355      };
44356  }
44357  /**
44358   * returns next boundaryPoint
44359   *
44360   * @param {BoundaryPoint} point
44361   * @param {Boolean} isSkipInnerOffset
44362   * @return {BoundaryPoint}
44363   */
44364  function nextPoint(point, isSkipInnerOffset) {
44365      var node, offset;
44366      if (nodeLength(point.node) === point.offset) {
44367          if (isEditable(point.node)) {
44368              return null;
44369          }
44370          node = point.node.parentNode;
44371          offset = position(point.node) + 1;
44372      }
44373      else if (hasChildren(point.node)) {
44374          node = point.node.childNodes[point.offset];
44375          offset = 0;
44376      }
44377      else {
44378          node = point.node;
44379          offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;
44380      }
44381      return {
44382          node: node,
44383          offset: offset
44384      };
44385  }
44386  /**
44387   * returns whether pointA and pointB is same or not.
44388   *
44389   * @param {BoundaryPoint} pointA
44390   * @param {BoundaryPoint} pointB
44391   * @return {Boolean}
44392   */
44393  function isSamePoint(pointA, pointB) {
44394      return pointA.node === pointB.node && pointA.offset === pointB.offset;
44395  }
44396  /**
44397   * returns whether point is visible (can set cursor) or not.
44398   *
44399   * @param {BoundaryPoint} point
44400   * @return {Boolean}
44401   */
44402  function isVisiblePoint(point) {
44403      if (isText(point.node) || !hasChildren(point.node) || isEmpty$1(point.node)) {
44404          return true;
44405      }
44406      var leftNode = point.node.childNodes[point.offset - 1];
44407      var rightNode = point.node.childNodes[point.offset];
44408      if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode))) {
44409          return true;
44410      }
44411      return false;
44412  }
44413  /**
44414   * @method prevPointUtil
44415   *
44416   * @param {BoundaryPoint} point
44417   * @param {Function} pred
44418   * @return {BoundaryPoint}
44419   */
44420  function prevPointUntil(point, pred) {
44421      while (point) {
44422          if (pred(point)) {
44423              return point;
44424          }
44425          point = prevPoint(point);
44426      }
44427      return null;
44428  }
44429  /**
44430   * @method nextPointUntil
44431   *
44432   * @param {BoundaryPoint} point
44433   * @param {Function} pred
44434   * @return {BoundaryPoint}
44435   */
44436  function nextPointUntil(point, pred) {
44437      while (point) {
44438          if (pred(point)) {
44439              return point;
44440          }
44441          point = nextPoint(point);
44442      }
44443      return null;
44444  }
44445  /**
44446   * returns whether point has character or not.
44447   *
44448   * @param {Point} point
44449   * @return {Boolean}
44450   */
44451  function isCharPoint(point) {
44452      if (!isText(point.node)) {
44453          return false;
44454      }
44455      var ch = point.node.nodeValue.charAt(point.offset - 1);
44456      return ch && (ch !== ' ' && ch !== NBSP_CHAR);
44457  }
44458  /**
44459   * @method walkPoint
44460   *
44461   * @param {BoundaryPoint} startPoint
44462   * @param {BoundaryPoint} endPoint
44463   * @param {Function} handler
44464   * @param {Boolean} isSkipInnerOffset
44465   */
44466  function walkPoint(startPoint, endPoint, handler, isSkipInnerOffset) {
44467      var point = startPoint;
44468      while (point) {
44469          handler(point);
44470          if (isSamePoint(point, endPoint)) {
44471              break;
44472          }
44473          var isSkipOffset = isSkipInnerOffset &&
44474              startPoint.node !== point.node &&
44475              endPoint.node !== point.node;
44476          point = nextPoint(point, isSkipOffset);
44477      }
44478  }
44479  /**
44480   * @method makeOffsetPath
44481   *
44482   * return offsetPath(array of offset) from ancestor
44483   *
44484   * @param {Node} ancestor - ancestor node
44485   * @param {Node} node
44486   */
44487  function makeOffsetPath(ancestor, node) {
44488      var ancestors = listAncestor(node, func.eq(ancestor));
44489      return ancestors.map(position).reverse();
44490  }
44491  /**
44492   * @method fromOffsetPath
44493   *
44494   * return element from offsetPath(array of offset)
44495   *
44496   * @param {Node} ancestor - ancestor node
44497   * @param {array} offsets - offsetPath
44498   */
44499  function fromOffsetPath(ancestor, offsets) {
44500      var current = ancestor;
44501      for (var i = 0, len = offsets.length; i < len; i++) {
44502          if (current.childNodes.length <= offsets[i]) {
44503              current = current.childNodes[current.childNodes.length - 1];
44504          }
44505          else {
44506              current = current.childNodes[offsets[i]];
44507          }
44508      }
44509      return current;
44510  }
44511  /**
44512   * @method splitNode
44513   *
44514   * split element or #text
44515   *
44516   * @param {BoundaryPoint} point
44517   * @param {Object} [options]
44518   * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
44519   * @param {Boolean} [options.isNotSplitEdgePoint] - default: false
44520   * @param {Boolean} [options.isDiscardEmptySplits] - default: false
44521   * @return {Node} right node of boundaryPoint
44522   */
44523  function splitNode(point, options) {
44524      var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML;
44525      var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint;
44526      var isDiscardEmptySplits = options && options.isDiscardEmptySplits;
44527      if (isDiscardEmptySplits) {
44528          isSkipPaddingBlankHTML = true;
44529      }
44530      // edge case
44531      if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) {
44532          if (isLeftEdgePoint(point)) {
44533              return point.node;
44534          }
44535          else if (isRightEdgePoint(point)) {
44536              return point.node.nextSibling;
44537          }
44538      }
44539      // split #text
44540      if (isText(point.node)) {
44541          return point.node.splitText(point.offset);
44542      }
44543      else {
44544          var childNode = point.node.childNodes[point.offset];
44545          var clone = insertAfter(point.node.cloneNode(false), point.node);
44546          appendChildNodes(clone, listNext(childNode));
44547          if (!isSkipPaddingBlankHTML) {
44548              paddingBlankHTML(point.node);
44549              paddingBlankHTML(clone);
44550          }
44551          if (isDiscardEmptySplits) {
44552              if (isEmpty$1(point.node)) {
44553                  remove(point.node);
44554              }
44555              if (isEmpty$1(clone)) {
44556                  remove(clone);
44557                  return point.node.nextSibling;
44558              }
44559          }
44560          return clone;
44561      }
44562  }
44563  /**
44564   * @method splitTree
44565   *
44566   * split tree by point
44567   *
44568   * @param {Node} root - split root
44569   * @param {BoundaryPoint} point
44570   * @param {Object} [options]
44571   * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false
44572   * @param {Boolean} [options.isNotSplitEdgePoint] - default: false
44573   * @return {Node} right node of boundaryPoint
44574   */
44575  function splitTree(root, point, options) {
44576      // ex) [#text, <span>, <p>]
44577      var ancestors = listAncestor(point.node, func.eq(root));
44578      if (!ancestors.length) {
44579          return null;
44580      }
44581      else if (ancestors.length === 1) {
44582          return splitNode(point, options);
44583      }
44584      return ancestors.reduce(function (node, parent) {
44585          if (node === point.node) {
44586              node = splitNode(point, options);
44587          }
44588          return splitNode({
44589              node: parent,
44590              offset: node ? position(node) : nodeLength(parent)
44591          }, options);
44592      });
44593  }
44594  /**
44595   * split point
44596   *
44597   * @param {Point} point
44598   * @param {Boolean} isInline
44599   * @return {Object}
44600   */
44601  function splitPoint(point, isInline) {
44602      // find splitRoot, container
44603      //  - inline: splitRoot is a child of paragraph
44604      //  - block: splitRoot is a child of bodyContainer
44605      var pred = isInline ? isPara : isBodyContainer;
44606      var ancestors = listAncestor(point.node, pred);
44607      var topAncestor = lists.last(ancestors) || point.node;
44608      var splitRoot, container;
44609      if (pred(topAncestor)) {
44610          splitRoot = ancestors[ancestors.length - 2];
44611          container = topAncestor;
44612      }
44613      else {
44614          splitRoot = topAncestor;
44615          container = splitRoot.parentNode;
44616      }
44617      // if splitRoot is exists, split with splitTree
44618      var pivot = splitRoot && splitTree(splitRoot, point, {
44619          isSkipPaddingBlankHTML: isInline,
44620          isNotSplitEdgePoint: isInline
44621      });
44622      // if container is point.node, find pivot with point.offset
44623      if (!pivot && container === point.node) {
44624          pivot = point.node.childNodes[point.offset];
44625      }
44626      return {
44627          rightNode: pivot,
44628          container: container
44629      };
44630  }
44631  function create(nodeName) {
44632      return document.createElement(nodeName);
44633  }
44634  function createText(text) {
44635      return document.createTextNode(text);
44636  }
44637  /**
44638   * @method remove
44639   *
44640   * remove node, (isRemoveChild: remove child or not)
44641   *
44642   * @param {Node} node
44643   * @param {Boolean} isRemoveChild
44644   */
44645  function remove(node, isRemoveChild) {
44646      if (!node || !node.parentNode) {
44647          return;
44648      }
44649      if (node.removeNode) {
44650          return node.removeNode(isRemoveChild);
44651      }
44652      var parent = node.parentNode;
44653      if (!isRemoveChild) {
44654          var nodes = [];
44655          for (var i = 0, len = node.childNodes.length; i < len; i++) {
44656              nodes.push(node.childNodes[i]);
44657          }
44658          for (var i = 0, len = nodes.length; i < len; i++) {
44659              parent.insertBefore(nodes[i], node);
44660          }
44661      }
44662      parent.removeChild(node);
44663  }
44664  /**
44665   * @method removeWhile
44666   *
44667   * @param {Node} node
44668   * @param {Function} pred
44669   */
44670  function removeWhile(node, pred) {
44671      while (node) {
44672          if (isEditable(node) || !pred(node)) {
44673              break;
44674          }
44675          var parent = node.parentNode;
44676          remove(node);
44677          node = parent;
44678      }
44679  }
44680  /**
44681   * @method replace
44682   *
44683   * replace node with provided nodeName
44684   *
44685   * @param {Node} node
44686   * @param {String} nodeName
44687   * @return {Node} - new node
44688   */
44689  function replace(node, nodeName) {
44690      if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) {
44691          return node;
44692      }
44693      var newNode = create(nodeName);
44694      if (node.style.cssText) {
44695          newNode.style.cssText = node.style.cssText;
44696      }
44697      appendChildNodes(newNode, lists.from(node.childNodes));
44698      insertAfter(newNode, node);
44699      remove(node);
44700      return newNode;
44701  }
44702  var isTextarea = makePredByNodeName('TEXTAREA');
44703  /**
44704   * @param {jQuery} $node
44705   * @param {Boolean} [stripLinebreaks] - default: false
44706   */
44707  function value($node, stripLinebreaks) {
44708      var val = isTextarea($node[0]) ? $node.val() : $node.html();
44709      if (stripLinebreaks) {
44710          return val.replace(/[\n\r]/g, '');
44711      }
44712      return val;
44713  }
44714  /**
44715   * @method html
44716   *
44717   * get the HTML contents of node
44718   *
44719   * @param {jQuery} $node
44720   * @param {Boolean} [isNewlineOnBlock]
44721   */
44722  function html($node, isNewlineOnBlock) {
44723      var markup = value($node);
44724      if (isNewlineOnBlock) {
44725          var regexTag = /<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g;
44726          markup = markup.replace(regexTag, function (match, endSlash, name) {
44727              name = name.toUpperCase();
44728              var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) &&
44729                  !!endSlash;
44730              var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name);
44731              return match + ((isEndOfInlineContainer || isBlockNode) ? '\n' : '');
44732          });
44733          markup = markup.trim();
44734      }
44735      return markup;
44736  }
44737  function posFromPlaceholder(placeholder) {
44738      var $placeholder = $$1(placeholder);
44739      var pos = $placeholder.offset();
44740      var height = $placeholder.outerHeight(true); // include margin
44741      return {
44742          left: pos.left,
44743          top: pos.top + height
44744      };
44745  }
44746  function attachEvents($node, events) {
44747      Object.keys(events).forEach(function (key) {
44748          $node.on(key, events[key]);
44749      });
44750  }
44751  function detachEvents($node, events) {
44752      Object.keys(events).forEach(function (key) {
44753          $node.off(key, events[key]);
44754      });
44755  }
44756  /**
44757   * @method isCustomStyleTag
44758   *
44759   * assert if a node contains a "note-styletag" class,
44760   * which implies that's a custom-made style tag node
44761   *
44762   * @param {Node} an HTML DOM node
44763   */
44764  function isCustomStyleTag(node) {
44765      return node && !isText(node) && lists.contains(node.classList, 'note-styletag');
44766  }
44767  var dom = {
44768      /** @property {String} NBSP_CHAR */
44769      NBSP_CHAR: NBSP_CHAR,
44770      /** @property {String} ZERO_WIDTH_NBSP_CHAR */
44771      ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR,
44772      /** @property {String} blank */
44773      blank: blankHTML,
44774      /** @property {String} emptyPara */
44775      emptyPara: "<p>" + blankHTML + "</p>",
44776      makePredByNodeName: makePredByNodeName,
44777      isEditable: isEditable,
44778      isControlSizing: isControlSizing,
44779      isText: isText,
44780      isElement: isElement,
44781      isVoid: isVoid,
44782      isPara: isPara,
44783      isPurePara: isPurePara,
44784      isHeading: isHeading,
44785      isInline: isInline,
44786      isBlock: func.not(isInline),
44787      isBodyInline: isBodyInline,
44788      isBody: isBody,
44789      isParaInline: isParaInline,
44790      isPre: isPre,
44791      isList: isList,
44792      isTable: isTable,
44793      isData: isData,
44794      isCell: isCell,
44795      isBlockquote: isBlockquote,
44796      isBodyContainer: isBodyContainer,
44797      isAnchor: isAnchor,
44798      isDiv: makePredByNodeName('DIV'),
44799      isLi: isLi,
44800      isBR: makePredByNodeName('BR'),
44801      isSpan: makePredByNodeName('SPAN'),
44802      isB: makePredByNodeName('B'),
44803      isU: makePredByNodeName('U'),
44804      isS: makePredByNodeName('S'),
44805      isI: makePredByNodeName('I'),
44806      isImg: makePredByNodeName('IMG'),
44807      isTextarea: isTextarea,
44808      isEmpty: isEmpty$1,
44809      isEmptyAnchor: func.and(isAnchor, isEmpty$1),
44810      isClosestSibling: isClosestSibling,
44811      withClosestSiblings: withClosestSiblings,
44812      nodeLength: nodeLength,
44813      isLeftEdgePoint: isLeftEdgePoint,
44814      isRightEdgePoint: isRightEdgePoint,
44815      isEdgePoint: isEdgePoint,
44816      isLeftEdgeOf: isLeftEdgeOf,
44817      isRightEdgeOf: isRightEdgeOf,
44818      isLeftEdgePointOf: isLeftEdgePointOf,
44819      isRightEdgePointOf: isRightEdgePointOf,
44820      prevPoint: prevPoint,
44821      nextPoint: nextPoint,
44822      isSamePoint: isSamePoint,
44823      isVisiblePoint: isVisiblePoint,
44824      prevPointUntil: prevPointUntil,
44825      nextPointUntil: nextPointUntil,
44826      isCharPoint: isCharPoint,
44827      walkPoint: walkPoint,
44828      ancestor: ancestor,
44829      singleChildAncestor: singleChildAncestor,
44830      listAncestor: listAncestor,
44831      lastAncestor: lastAncestor,
44832      listNext: listNext,
44833      listPrev: listPrev,
44834      listDescendant: listDescendant,
44835      commonAncestor: commonAncestor,
44836      wrap: wrap,
44837      insertAfter: insertAfter,
44838      appendChildNodes: appendChildNodes,
44839      position: position,
44840      hasChildren: hasChildren,
44841      makeOffsetPath: makeOffsetPath,
44842      fromOffsetPath: fromOffsetPath,
44843      splitTree: splitTree,
44844      splitPoint: splitPoint,
44845      create: create,
44846      createText: createText,
44847      remove: remove,
44848      removeWhile: removeWhile,
44849      replace: replace,
44850      html: html,
44851      value: value,
44852      posFromPlaceholder: posFromPlaceholder,
44853      attachEvents: attachEvents,
44854      detachEvents: detachEvents,
44855      isCustomStyleTag: isCustomStyleTag
44856  };
44857
44858  var Context = /** @class */ (function () {
44859      /**
44860       * @param {jQuery} $note
44861       * @param {Object} options
44862       */
44863      function Context($note, options) {
44864          this.ui = $$1.summernote.ui;
44865          this.$note = $note;
44866          this.memos = {};
44867          this.modules = {};
44868          this.layoutInfo = {};
44869          this.options = options;
44870          this.initialize();
44871      }
44872      /**
44873       * create layout and initialize modules and other resources
44874       */
44875      Context.prototype.initialize = function () {
44876          this.layoutInfo = this.ui.createLayout(this.$note, this.options);
44877          this._initialize();
44878          this.$note.hide();
44879          return this;
44880      };
44881      /**
44882       * destroy modules and other resources and remove layout
44883       */
44884      Context.prototype.destroy = function () {
44885          this._destroy();
44886          this.$note.removeData('summernote');
44887          this.ui.removeLayout(this.$note, this.layoutInfo);
44888      };
44889      /**
44890       * destory modules and other resources and initialize it again
44891       */
44892      Context.prototype.reset = function () {
44893          var disabled = this.isDisabled();
44894          this.code(dom.emptyPara);
44895          this._destroy();
44896          this._initialize();
44897          if (disabled) {
44898              this.disable();
44899          }
44900      };
44901      Context.prototype._initialize = function () {
44902          var _this = this;
44903          // add optional buttons
44904          var buttons = $$1.extend({}, this.options.buttons);
44905          Object.keys(buttons).forEach(function (key) {
44906              _this.memo('button.' + key, buttons[key]);
44907          });
44908          var modules = $$1.extend({}, this.options.modules, $$1.summernote.plugins || {});
44909          // add and initialize modules
44910          Object.keys(modules).forEach(function (key) {
44911              _this.module(key, modules[key], true);
44912          });
44913          Object.keys(this.modules).forEach(function (key) {
44914              _this.initializeModule(key);
44915          });
44916      };
44917      Context.prototype._destroy = function () {
44918          var _this = this;
44919          // destroy modules with reversed order
44920          Object.keys(this.modules).reverse().forEach(function (key) {
44921              _this.removeModule(key);
44922          });
44923          Object.keys(this.memos).forEach(function (key) {
44924              _this.removeMemo(key);
44925          });
44926          // trigger custom onDestroy callback
44927          this.triggerEvent('destroy', this);
44928      };
44929      Context.prototype.code = function (html) {
44930          var isActivated = this.invoke('codeview.isActivated');
44931          if (html === undefined) {
44932              this.invoke('codeview.sync');
44933              return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html();
44934          }
44935          else {
44936              if (isActivated) {
44937                  this.layoutInfo.codable.val(html);
44938              }
44939              else {
44940                  this.layoutInfo.editable.html(html);
44941              }
44942              this.$note.val(html);
44943              this.triggerEvent('change', html, this.layoutInfo.editable);
44944          }
44945      };
44946      Context.prototype.isDisabled = function () {
44947          return this.layoutInfo.editable.attr('contenteditable') === 'false';
44948      };
44949      Context.prototype.enable = function () {
44950          this.layoutInfo.editable.attr('contenteditable', true);
44951          this.invoke('toolbar.activate', true);
44952          this.triggerEvent('disable', false);
44953      };
44954      Context.prototype.disable = function () {
44955          // close codeview if codeview is opend
44956          if (this.invoke('codeview.isActivated')) {
44957              this.invoke('codeview.deactivate');
44958          }
44959          this.layoutInfo.editable.attr('contenteditable', false);
44960          this.invoke('toolbar.deactivate', true);
44961          this.triggerEvent('disable', true);
44962      };
44963      Context.prototype.triggerEvent = function () {
44964          var namespace = lists.head(arguments);
44965          var args = lists.tail(lists.from(arguments));
44966          var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')];
44967          if (callback) {
44968              callback.apply(this.$note[0], args);
44969          }
44970          this.$note.trigger('summernote.' + namespace, args);
44971      };
44972      Context.prototype.initializeModule = function (key) {
44973          var module = this.modules[key];
44974          module.shouldInitialize = module.shouldInitialize || func.ok;
44975          if (!module.shouldInitialize()) {
44976              return;
44977          }
44978          // initialize module
44979          if (module.initialize) {
44980              module.initialize();
44981          }
44982          // attach events
44983          if (module.events) {
44984              dom.attachEvents(this.$note, module.events);
44985          }
44986      };
44987      Context.prototype.module = function (key, ModuleClass, withoutIntialize) {
44988          if (arguments.length === 1) {
44989              return this.modules[key];
44990          }
44991          this.modules[key] = new ModuleClass(this);
44992          if (!withoutIntialize) {
44993              this.initializeModule(key);
44994          }
44995      };
44996      Context.prototype.removeModule = function (key) {
44997          var module = this.modules[key];
44998          if (module.shouldInitialize()) {
44999              if (module.events) {
45000                  dom.detachEvents(this.$note, module.events);
45001              }
45002              if (module.destroy) {
45003                  module.destroy();
45004              }
45005          }
45006          delete this.modules[key];
45007      };
45008      Context.prototype.memo = function (key, obj) {
45009          if (arguments.length === 1) {
45010              return this.memos[key];
45011          }
45012          this.memos[key] = obj;
45013      };
45014      Context.prototype.removeMemo = function (key) {
45015          if (this.memos[key] && this.memos[key].destroy) {
45016              this.memos[key].destroy();
45017          }
45018          delete this.memos[key];
45019      };
45020      /**
45021       * Some buttons need to change their visual style immediately once they get pressed
45022       */
45023      Context.prototype.createInvokeHandlerAndUpdateState = function (namespace, value) {
45024          var _this = this;
45025          return function (event) {
45026              _this.createInvokeHandler(namespace, value)(event);
45027              _this.invoke('buttons.updateCurrentStyle');
45028          };
45029      };
45030      Context.prototype.createInvokeHandler = function (namespace, value) {
45031          var _this = this;
45032          return function (event) {
45033              event.preventDefault();
45034              var $target = $$1(event.target);
45035              _this.invoke(namespace, value || $target.closest('[data-value]').data('value'), $target);
45036          };
45037      };
45038      Context.prototype.invoke = function () {
45039          var namespace = lists.head(arguments);
45040          var args = lists.tail(lists.from(arguments));
45041          var splits = namespace.split('.');
45042          var hasSeparator = splits.length > 1;
45043          var moduleName = hasSeparator && lists.head(splits);
45044          var methodName = hasSeparator ? lists.last(splits) : lists.head(splits);
45045          var module = this.modules[moduleName || 'editor'];
45046          if (!moduleName && this[methodName]) {
45047              return this[methodName].apply(this, args);
45048          }
45049          else if (module && module[methodName] && module.shouldInitialize()) {
45050              return module[methodName].apply(module, args);
45051          }
45052      };
45053      return Context;
45054  }());
45055
45056  $$1.fn.extend({
45057      /**
45058       * Summernote API
45059       *
45060       * @param {Object|String}
45061       * @return {this}
45062       */
45063      summernote: function () {
45064          var type = $$1.type(lists.head(arguments));
45065          var isExternalAPICalled = type === 'string';
45066          var hasInitOptions = type === 'object';
45067          var options = $$1.extend({}, $$1.summernote.options, hasInitOptions ? lists.head(arguments) : {});
45068          // Update options
45069          options.langInfo = $$1.extend(true, {}, $$1.summernote.lang['en-US'], $$1.summernote.lang[options.lang]);
45070          options.icons = $$1.extend(true, {}, $$1.summernote.options.icons, options.icons);
45071          options.tooltip = options.tooltip === 'auto' ? !env.isSupportTouch : options.tooltip;
45072          this.each(function (idx, note) {
45073              var $note = $$1(note);
45074              if (!$note.data('summernote')) {
45075                  var context = new Context($note, options);
45076                  $note.data('summernote', context);
45077                  $note.data('summernote').triggerEvent('init', context.layoutInfo);
45078              }
45079          });
45080          var $note = this.first();
45081          if ($note.length) {
45082              var context = $note.data('summernote');
45083              if (isExternalAPICalled) {
vendor: 3,407 bytes, lines 45084-45168
45084                  return context.invoke.apply(context, lists.from(arguments));
45085              }
45086              else if (options.focus) {
45087                  context.invoke('editor.focus');
45088              }
45089          }
45090          return this;
45091      }
45092  });
45093
45094  /**
45095   * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js
45096   *
45097   * @param {TextRange} textRange
45098   * @param {Boolean} isStart
45099   * @return {BoundaryPoint}
45100   *
45101   * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx
45102   */
45103  function textRangeToPoint(textRange, isStart) {
45104      var container = textRange.parentElement();
45105      var offset;
45106      var tester = document.body.createTextRange();
45107      var prevContainer;
45108      var childNodes = lists.from(container.childNodes);
45109      for (offset = 0; offset < childNodes.length; offset++) {
45110          if (dom.isText(childNodes[offset])) {
45111              continue;
45112          }
45113          tester.moveToElementText(childNodes[offset]);
45114          if (tester.compareEndPoints('StartToStart', textRange) >= 0) {
45115              break;
45116          }
45117          prevContainer = childNodes[offset];
45118      }
45119      if (offset !== 0 && dom.isText(childNodes[offset - 1])) {
45120          var textRangeStart = document.body.createTextRange();
45121          var curTextNode = null;
45122          textRangeStart.moveToElementText(prevContainer || container);
45123          textRangeStart.collapse(!prevContainer);
45124          curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;
45125          var pointTester = textRange.duplicate();
45126          pointTester.setEndPoint('StartToStart', textRangeStart);
45127          var textCount = pointTester.text.replace(/[\r\n]/g, '').length;
45128          while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {
45129              textCount -= curTextNode.nodeValue.length;
45130              curTextNode = curTextNode.nextSibling;
45131          }
45132          // [workaround] enforce IE to re-reference curTextNode, hack
45133          var dummy = curTextNode.nodeValue; // eslint-disable-line
45134          if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) &&
45135              textCount === curTextNode.nodeValue.length) {
45136              textCount -= curTextNode.nodeValue.length;
45137              curTextNode = curTextNode.nextSibling;
45138          }
45139          container = curTextNode;
45140          offset = textCount;
45141      }
45142      return {
45143          cont: container,
45144          offset: offset
45145      };
45146  }
45147  /**
45148   * return TextRange from boundary point (inspired by google closure-library)
45149   * @param {BoundaryPoint} point
45150   * @return {TextRange}
45151   */
45152  function pointToTextRange(point) {
45153      var textRangeInfo = function (container, offset) {
45154          var node, isCollapseToStart;
45155          if (dom.isText(container)) {
45156              var prevTextNodes = dom.listPrev(container, func.not(dom.isText));
45157              var prevContainer = lists.last(prevTextNodes).previousSibling;
45158              node = prevContainer || container.parentNode;
45159              offset += lists.sum(lists.tail(prevTextNodes), dom.nodeLength);
45160              isCollapseToStart = !prevContainer;
45161          }
45162          else {
45163              node = container.childNodes[offset] || container;
45164              if (dom.isText(node)) {
45165                  return textRangeInfo(node, 0);
45166              }
45167              offset = 0;
45168              isCollapseToStart = false;
45169          }
45170          return {
45171              node: node,
45172              collapseToStart: isCollapseToStart,
45173              offset: offset
45174          };
45175      };
45176      var textRange = document.body.createTextRange();
45177      var info = textRangeInfo(point.node, point.offset);
45178      textRange.moveToElementText(info.node);
45179      textRange.collapse(info.collapseToStart);
45180      textRange.moveStart('character', info.offset);
45181      return textRange;
45182  }
45183  /**
45184     * Wrapped Range
45185     *
45186     * @constructor
45187     * @param {Node} sc - start container
45188     * @param {Number} so - start offset
45189     * @param {Node} ec - end container
45190     * @param {Number} eo - end offset
45191     */
45192  var WrappedRange = /** @class */ (function () {
45193      function WrappedRange(sc, so, ec, eo) {
45194          this.sc = sc;
45195          this.so = so;
45196          this.ec = ec;
45197          this.eo = eo;
45198          // isOnEditable: judge whether range is on editable or not
45199          this.isOnEditable = this.makeIsOn(dom.isEditable);
45200          // isOnList: judge whether range is on list node or not
45201          this.isOnList = this.makeIsOn(dom.isList);
45202          // isOnAnchor: judge whether range is on anchor node or not
45203          this.isOnAnchor = this.makeIsOn(dom.isAnchor);
45204          // isOnCell: judge whether range is on cell node or not
45205          this.isOnCell = this.makeIsOn(dom.isCell);
45206          // isOnData: judge whether range is on data node or not
45207          this.isOnData = this.makeIsOn(dom.isData);
45208      }
45209      // nativeRange: get nativeRange from sc, so, ec, eo
45210      WrappedRange.prototype.nativeRange = function () {
45211          if (env.isW3CRangeSupport) {
45212              var w3cRange = document.createRange();
45213              w3cRange.setStart(this.sc, this.sc.data && this.so > this.sc.data.length ? 0 : this.so);
45214              w3cRange.setEnd(this.ec, this.sc.data ? Math.min(this.eo, this.sc.data.length) : this.eo);
45215              return w3cRange;
45216          }
45217          else {
45218              var textRange = pointToTextRange({
45219                  node: this.sc,
45220                  offset: this.so
45221              });
45222              textRange.setEndPoint('EndToEnd', pointToTextRange({
45223                  node: this.ec,
45224                  offset: this.eo
45225              }));
45226              return textRange;
45227          }
45228      };
45229      WrappedRange.prototype.getPoints = function () {
45230          return {
45231              sc: this.sc,
45232              so: this.so,
45233              ec: this.ec,
45234              eo: this.eo
45235          };
45236      };
45237      WrappedRange.prototype.getStartPoint = function () {
45238          return {
45239              node: this.sc,
45240              offset: this.so
45241          };
45242      };
45243      WrappedRange.prototype.getEndPoint = function () {
45244          return {
45245              node: this.ec,
45246              offset: this.eo
45247          };
45248      };
45249      /**
45250       * select update visible range
45251       */
45252      WrappedRange.prototype.select = function () {
45253          var nativeRng = this.nativeRange();
45254          if (env.isW3CRangeSupport) {
45255              var selection = document.getSelection();
45256              if (selection.rangeCount > 0) {
45257                  selection.removeAllRanges();
45258              }
45259              selection.addRange(nativeRng);
45260          }
45261          else {
45262              nativeRng.select();
45263          }
45264          return this;
45265      };
45266      /**
45267       * Moves the scrollbar to start container(sc) of current range
45268       *
45269       * @return {WrappedRange}
45270       */
45271      WrappedRange.prototype.scrollIntoView = function (container) {
45272          var height = $$1(container).height();
45273          if (container.scrollTop + height < this.sc.offsetTop) {
45274              container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop);
45275          }
45276          return this;
45277      };
45278      /**
45279       * @return {WrappedRange}
45280       */
45281      WrappedRange.prototype.normalize = function () {
45282          /**
45283           * @param {BoundaryPoint} point
45284           * @param {Boolean} isLeftToRight - true: prefer to choose right node
45285           *                                - false: prefer to choose left node
45286           * @return {BoundaryPoint}
45287           */
45288          var getVisiblePoint = function (point, isLeftToRight) {
45289              // Just use the given point [XXX:Adhoc]
45290              //  - case 01. if the point is on the middle of the node
45291              //  - case 02. if the point is on the right edge and prefer to choose left node
45292              //  - case 03. if the point is on the left edge and prefer to choose right node
45293              //  - case 04. if the point is on the right edge and prefer to choose right node but the node is void
45294              //  - case 05. if the point is on the left edge and prefer to choose left node but the node is void
45295              //  - case 06. if the point is on the block node and there is no children
45296              if (dom.isVisiblePoint(point)) {
45297                  if (!dom.isEdgePoint(point) ||
45298                      (dom.isRightEdgePoint(point) && !isLeftToRight) ||
45299                      (dom.isLeftEdgePoint(point) && isLeftToRight) ||
45300                      (dom.isRightEdgePoint(point) && isLeftToRight && dom.isVoid(point.node.nextSibling)) ||
45301                      (dom.isLeftEdgePoint(point) && !isLeftToRight && dom.isVoid(point.node.previousSibling)) ||
45302                      (dom.isBlock(point.node) && dom.isEmpty(point.node))) {
45303                      return point;
45304                  }
45305              }
45306              // point on block's edge
45307              var block = dom.ancestor(point.node, dom.isBlock);
45308              if (((dom.isLeftEdgePointOf(point, block) || dom.isVoid(dom.prevPoint(point).node)) && !isLeftToRight) ||
45309                  ((dom.isRightEdgePointOf(point, block) || dom.isVoid(dom.nextPoint(point).node)) && isLeftToRight)) {
45310                  // returns point already on visible point
45311                  if (dom.isVisiblePoint(point)) {
45312                      return point;
45313                  }
45314                  // reverse direction
45315                  isLeftToRight = !isLeftToRight;
45316              }
45317              var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint)
45318                  : dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint);
45319              return nextPoint || point;
45320          };
45321          var endPoint = getVisiblePoint(this.getEndPoint(), false);
45322          var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true);
45323          return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
45324      };
45325      /**
45326       * returns matched nodes on range
45327       *
45328       * @param {Function} [pred] - predicate function
45329       * @param {Object} [options]
45330       * @param {Boolean} [options.includeAncestor]
45331       * @param {Boolean} [options.fullyContains]
45332       * @return {Node[]}
45333       */
45334      WrappedRange.prototype.nodes = function (pred, options) {
45335          pred = pred || func.ok;
45336          var includeAncestor = options && options.includeAncestor;
45337          var fullyContains = options && options.fullyContains;
vendor: 17,235 bytes, lines 45338-45849
45338          // TODO compare points and sort
45339          var startPoint = this.getStartPoint();
45340          var endPoint = this.getEndPoint();
45341          var nodes = [];
45342          var leftEdgeNodes = [];
45343          dom.walkPoint(startPoint, endPoint, function (point) {
45344              if (dom.isEditable(point.node)) {
45345                  return;
45346              }
45347              var node;
45348              if (fullyContains) {
45349                  if (dom.isLeftEdgePoint(point)) {
45350                      leftEdgeNodes.push(point.node);
45351                  }
45352                  if (dom.isRightEdgePoint(point) && lists.contains(leftEdgeNodes, point.node)) {
45353                      node = point.node;
45354                  }
45355              }
45356              else if (includeAncestor) {
45357                  node = dom.ancestor(point.node, pred);
45358              }
45359              else {
45360                  node = point.node;
45361              }
45362              if (node && pred(node)) {
45363                  nodes.push(node);
45364              }
45365          }, true);
45366          return lists.unique(nodes);
45367      };
45368      /**
45369       * returns commonAncestor of range
45370       * @return {Element} - commonAncestor
45371       */
45372      WrappedRange.prototype.commonAncestor = function () {
45373          return dom.commonAncestor(this.sc, this.ec);
45374      };
45375      /**
45376       * returns expanded range by pred
45377       *
45378       * @param {Function} pred - predicate function
45379       * @return {WrappedRange}
45380       */
45381      WrappedRange.prototype.expand = function (pred) {
45382          var startAncestor = dom.ancestor(this.sc, pred);
45383          var endAncestor = dom.ancestor(this.ec, pred);
45384          if (!startAncestor && !endAncestor) {
45385              return new WrappedRange(this.sc, this.so, this.ec, this.eo);
45386          }
45387          var boundaryPoints = this.getPoints();
45388          if (startAncestor) {
45389              boundaryPoints.sc = startAncestor;
45390              boundaryPoints.so = 0;
45391          }
45392          if (endAncestor) {
45393              boundaryPoints.ec = endAncestor;
45394              boundaryPoints.eo = dom.nodeLength(endAncestor);
45395          }
45396          return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo);
45397      };
45398      /**
45399       * @param {Boolean} isCollapseToStart
45400       * @return {WrappedRange}
45401       */
45402      WrappedRange.prototype.collapse = function (isCollapseToStart) {
45403          if (isCollapseToStart) {
45404              return new WrappedRange(this.sc, this.so, this.sc, this.so);
45405          }
45406          else {
45407              return new WrappedRange(this.ec, this.eo, this.ec, this.eo);
45408          }
45409      };
45410      /**
45411       * splitText on range
45412       */
45413      WrappedRange.prototype.splitText = function () {
45414          var isSameContainer = this.sc === this.ec;
45415          var boundaryPoints = this.getPoints();
45416          if (dom.isText(this.ec) && !dom.isEdgePoint(this.getEndPoint())) {
45417              this.ec.splitText(this.eo);
45418          }
45419          if (dom.isText(this.sc) && !dom.isEdgePoint(this.getStartPoint())) {
45420              boundaryPoints.sc = this.sc.splitText(this.so);
45421              boundaryPoints.so = 0;
45422              if (isSameContainer) {
45423                  boundaryPoints.ec = boundaryPoints.sc;
45424                  boundaryPoints.eo = this.eo - this.so;
45425              }
45426          }
45427          return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo);
45428      };
45429      /**
45430       * delete contents on range
45431       * @return {WrappedRange}
45432       */
45433      WrappedRange.prototype.deleteContents = function () {
45434          if (this.isCollapsed()) {
45435              return this;
45436          }
45437          var rng = this.splitText();
45438          var nodes = rng.nodes(null, {
45439              fullyContains: true
45440          });
45441          // find new cursor point
45442          var point = dom.prevPointUntil(rng.getStartPoint(), function (point) {
45443              return !lists.contains(nodes, point.node);
45444          });
45445          var emptyParents = [];
45446          $$1.each(nodes, function (idx, node) {
45447              // find empty parents
45448              var parent = node.parentNode;
45449              if (point.node !== parent && dom.nodeLength(parent) === 1) {
45450                  emptyParents.push(parent);
45451              }
45452              dom.remove(node, false);
45453          });
45454          // remove empty parents
45455          $$1.each(emptyParents, function (idx, node) {
45456              dom.remove(node, false);
45457          });
45458          return new WrappedRange(point.node, point.offset, point.node, point.offset).normalize();
45459      };
45460      /**
45461       * makeIsOn: return isOn(pred) function
45462       */
45463      WrappedRange.prototype.makeIsOn = function (pred) {
45464          return function () {
45465              var ancestor = dom.ancestor(this.sc, pred);
45466              return !!ancestor && (ancestor === dom.ancestor(this.ec, pred));
45467          };
45468      };
45469      /**
45470       * @param {Function} pred
45471       * @return {Boolean}
45472       */
45473      WrappedRange.prototype.isLeftEdgeOf = function (pred) {
45474          if (!dom.isLeftEdgePoint(this.getStartPoint())) {
45475              return false;
45476          }
45477          var node = dom.ancestor(this.sc, pred);
45478          return node && dom.isLeftEdgeOf(this.sc, node);
45479      };
45480      /**
45481       * returns whether range was collapsed or not
45482       */
45483      WrappedRange.prototype.isCollapsed = function () {
45484          return this.sc === this.ec && this.so === this.eo;
45485      };
45486      /**
45487       * wrap inline nodes which children of body with paragraph
45488       *
45489       * @return {WrappedRange}
45490       */
45491      WrappedRange.prototype.wrapBodyInlineWithPara = function () {
45492          if (dom.isBodyContainer(this.sc) && dom.isEmpty(this.sc)) {
45493              this.sc.innerHTML = dom.emptyPara;
45494              return new WrappedRange(this.sc.firstChild, 0, this.sc.firstChild, 0);
45495          }
45496          /**
45497           * [workaround] firefox often create range on not visible point. so normalize here.
45498           *  - firefox: |<p>text</p>|
45499           *  - chrome: <p>|text|</p>
45500           */
45501          var rng = this.normalize();
45502          if (dom.isParaInline(this.sc) || dom.isPara(this.sc)) {
45503              return rng;
45504          }
45505          // find inline top ancestor
45506          var topAncestor;
45507          if (dom.isInline(rng.sc)) {
45508              var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline));
45509              topAncestor = lists.last(ancestors);
45510              if (!dom.isInline(topAncestor)) {
45511                  topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so];
45512              }
45513          }
45514          else {
45515              topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0];
45516          }
45517          // siblings not in paragraph
45518          var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse();
45519          inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline));
45520          // wrap with paragraph
45521          if (inlineSiblings.length) {
45522              var para = dom.wrap(lists.head(inlineSiblings), 'p');
45523              dom.appendChildNodes(para, lists.tail(inlineSiblings));
45524          }
45525          return this.normalize();
45526      };
45527      /**
45528       * insert node at current cursor
45529       *
45530       * @param {Node} node
45531       * @return {Node}
45532       */
45533      WrappedRange.prototype.insertNode = function (node) {
45534          var rng = this.wrapBodyInlineWithPara().deleteContents();
45535          var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node));
45536          if (info.rightNode) {
45537              info.rightNode.parentNode.insertBefore(node, info.rightNode);
45538          }
45539          else {
45540              info.container.appendChild(node);
45541          }
45542          return node;
45543      };
45544      /**
45545       * insert html at current cursor
45546       */
45547      WrappedRange.prototype.pasteHTML = function (markup) {
45548          var contentsContainer = $$1('<div></div>').html(markup)[0];
45549          var childNodes = lists.from(contentsContainer.childNodes);
45550          var rng = this.wrapBodyInlineWithPara().deleteContents();
45551          if (rng.so > 0) {
45552              childNodes = childNodes.reverse();
45553          }
45554          childNodes = childNodes.map(function (childNode) {
45555              return rng.insertNode(childNode);
45556          });
45557          if (rng.so > 0) {
45558              childNodes = childNodes.reverse();
45559          }
45560          return childNodes;
45561      };
45562      /**
45563       * returns text in range
45564       *
45565       * @return {String}
45566       */
45567      WrappedRange.prototype.toString = function () {
45568          var nativeRng = this.nativeRange();
45569          return env.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text;
45570      };
45571      /**
45572       * returns range for word before cursor
45573       *
45574       * @param {Boolean} [findAfter] - find after cursor, default: false
45575       * @return {WrappedRange}
45576       */
45577      WrappedRange.prototype.getWordRange = function (findAfter) {
45578          var endPoint = this.getEndPoint();
45579          if (!dom.isCharPoint(endPoint)) {
45580              return this;
45581          }
45582          var startPoint = dom.prevPointUntil(endPoint, function (point) {
45583              return !dom.isCharPoint(point);
45584          });
45585          if (findAfter) {
45586              endPoint = dom.nextPointUntil(endPoint, function (point) {
45587                  return !dom.isCharPoint(point);
45588              });
45589          }
45590          return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset);
45591      };
45592      /**
45593       * create offsetPath bookmark
45594       *
45595       * @param {Node} editable
45596       */
45597      WrappedRange.prototype.bookmark = function (editable) {
45598          return {
45599              s: {
45600                  path: dom.makeOffsetPath(editable, this.sc),
45601                  offset: this.so
45602              },
45603              e: {
45604                  path: dom.makeOffsetPath(editable, this.ec),
45605                  offset: this.eo
45606              }
45607          };
45608      };
45609      /**
45610       * create offsetPath bookmark base on paragraph
45611       *
45612       * @param {Node[]} paras
45613       */
45614      WrappedRange.prototype.paraBookmark = function (paras) {
45615          return {
45616              s: {
45617                  path: lists.tail(dom.makeOffsetPath(lists.head(paras), this.sc)),
45618                  offset: this.so
45619              },
45620              e: {
45621                  path: lists.tail(dom.makeOffsetPath(lists.last(paras), this.ec)),
45622                  offset: this.eo
45623              }
45624          };
45625      };
45626      /**
45627       * getClientRects
45628       * @return {Rect[]}
45629       */
45630      WrappedRange.prototype.getClientRects = function () {
45631          var nativeRng = this.nativeRange();
45632          return nativeRng.getClientRects();
45633      };
45634      return WrappedRange;
45635  }());
45636  /**
45637   * Data structure
45638   *  * BoundaryPoint: a point of dom tree
45639   *  * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range
45640   *
45641   * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position
45642   */
45643  var range = {
45644      /**
45645       * create Range Object From arguments or Browser Selection
45646       *
45647       * @param {Node} sc - start container
45648       * @param {Number} so - start offset
45649       * @param {Node} ec - end container
45650       * @param {Number} eo - end offset
45651       * @return {WrappedRange}
45652       */
45653      create: function (sc, so, ec, eo) {
45654          if (arguments.length === 4) {
45655              return new WrappedRange(sc, so, ec, eo);
45656          }
45657          else if (arguments.length === 2) { // collapsed
45658              ec = sc;
45659              eo = so;
45660              return new WrappedRange(sc, so, ec, eo);
45661          }
45662          else {
45663              var wrappedRange = this.createFromSelection();
45664              if (!wrappedRange && arguments.length === 1) {
45665                  wrappedRange = this.createFromNode(arguments[0]);
45666                  return wrappedRange.collapse(dom.emptyPara === arguments[0].innerHTML);
45667              }
45668              return wrappedRange;
45669          }
45670      },
45671      createFromSelection: function () {
45672          var sc, so, ec, eo;
45673          if (env.isW3CRangeSupport) {
45674              var selection = document.getSelection();
45675              if (!selection || selection.rangeCount === 0) {
45676                  return null;
45677              }
45678              else if (dom.isBody(selection.anchorNode)) {
45679                  // Firefox: returns entire body as range on initialization.
45680                  // We won't never need it.
45681                  return null;
45682              }
45683              var nativeRng = selection.getRangeAt(0);
45684              sc = nativeRng.startContainer;
45685              so = nativeRng.startOffset;
45686              ec = nativeRng.endContainer;
45687              eo = nativeRng.endOffset;
45688          }
45689          else { // IE8: TextRange
45690              var textRange = document.selection.createRange();
45691              var textRangeEnd = textRange.duplicate();
45692              textRangeEnd.collapse(false);
45693              var textRangeStart = textRange;
45694              textRangeStart.collapse(true);
45695              var startPoint = textRangeToPoint(textRangeStart, true);
45696              var endPoint = textRangeToPoint(textRangeEnd, false);
45697              // same visible point case: range was collapsed.
45698              if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) &&
45699                  dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) &&
45700                  endPoint.node.nextSibling === startPoint.node) {
45701                  startPoint = endPoint;
45702              }
45703              sc = startPoint.cont;
45704              so = startPoint.offset;
45705              ec = endPoint.cont;
45706              eo = endPoint.offset;
45707          }
45708          return new WrappedRange(sc, so, ec, eo);
45709      },
45710      /**
45711       * @method
45712       *
45713       * create WrappedRange from node
45714       *
45715       * @param {Node} node
45716       * @return {WrappedRange}
45717       */
45718      createFromNode: function (node) {
45719          var sc = node;
45720          var so = 0;
45721          var ec = node;
45722          var eo = dom.nodeLength(ec);
45723          // browsers can't target a picture or void node
45724          if (dom.isVoid(sc)) {
45725              so = dom.listPrev(sc).length - 1;
45726              sc = sc.parentNode;
45727          }
45728          if (dom.isBR(ec)) {
45729              eo = dom.listPrev(ec).length - 1;
45730              ec = ec.parentNode;
45731          }
45732          else if (dom.isVoid(ec)) {
45733              eo = dom.listPrev(ec).length;
45734              ec = ec.parentNode;
45735          }
45736          return this.create(sc, so, ec, eo);
45737      },
45738      /**
45739       * create WrappedRange from node after position
45740       *
45741       * @param {Node} node
45742       * @return {WrappedRange}
45743       */
45744      createFromNodeBefore: function (node) {
45745          return this.createFromNode(node).collapse(true);
45746      },
45747      /**
45748       * create WrappedRange from node after position
45749       *
45750       * @param {Node} node
45751       * @return {WrappedRange}
45752       */
45753      createFromNodeAfter: function (node) {
45754          return this.createFromNode(node).collapse();
45755      },
45756      /**
45757       * @method
45758       *
45759       * create WrappedRange from bookmark
45760       *
45761       * @param {Node} editable
45762       * @param {Object} bookmark
45763       * @return {WrappedRange}
45764       */
45765      createFromBookmark: function (editable, bookmark) {
45766          var sc = dom.fromOffsetPath(editable, bookmark.s.path);
45767          var so = bookmark.s.offset;
45768          var ec = dom.fromOffsetPath(editable, bookmark.e.path);
45769          var eo = bookmark.e.offset;
45770          return new WrappedRange(sc, so, ec, eo);
45771      },
45772      /**
45773       * @method
45774       *
45775       * create WrappedRange from paraBookmark
45776       *
45777       * @param {Object} bookmark
45778       * @param {Node[]} paras
45779       * @return {WrappedRange}
45780       */
45781      createFromParaBookmark: function (bookmark, paras) {
45782          var so = bookmark.s.offset;
45783          var eo = bookmark.e.offset;
45784          var sc = dom.fromOffsetPath(lists.head(paras), bookmark.s.path);
45785          var ec = dom.fromOffsetPath(lists.last(paras), bookmark.e.path);
45786          return new WrappedRange(sc, so, ec, eo);
45787      }
45788  };
45789
45790  var KEY_MAP = {
45791      'BACKSPACE': 8,
45792      'TAB': 9,
45793      'ENTER': 13,
45794      'SPACE': 32,
45795      'DELETE': 46,
45796      // Arrow
45797      'LEFT': 37,
45798      'UP': 38,
45799      'RIGHT': 39,
45800      'DOWN': 40,
45801      // Number: 0-9
45802      'NUM0': 48,
45803      'NUM1': 49,
45804      'NUM2': 50,
45805      'NUM3': 51,
45806      'NUM4': 52,
45807      'NUM5': 53,
45808      'NUM6': 54,
45809      'NUM7': 55,
45810      'NUM8': 56,
45811      // Alphabet: a-z
45812      'B': 66,
45813      'E': 69,
45814      'I': 73,
45815      'J': 74,
45816      'K': 75,
45817      'L': 76,
45818      'R': 82,
45819      'S': 83,
45820      'U': 85,
45821      'V': 86,
45822      'Y': 89,
45823      'Z': 90,
45824      'SLASH': 191,
45825      'LEFTBRACKET': 219,
45826      'BACKSLASH': 220,
45827      'RIGHTBRACKET': 221
45828  };
45829  /**
45830   * @class core.key
45831   *
45832   * Object for keycodes.
45833   *
45834   * @singleton
45835   * @alternateClassName key
45836   */
45837  var key = {
45838      /**
45839       * @method isEdit
45840       *
45841       * @param {Number} keyCode
45842       * @return {Boolean}
45843       */
45844      isEdit: function (keyCode) {
45845          return lists.contains([
45846              KEY_MAP.BACKSPACE,
45847              KEY_MAP.TAB,
45848              KEY_MAP.ENTER,
45849              KEY_MAP.SPACE,
45850              KEY_MAP.DELETE,
45851          ], keyCode);
45852      },
45853      /**
45854       * @method isMove
45855       *
45856       * @param {Number} keyCode
45857       * @return {Boolean}
45858       */
45859      isMove: function (keyCode) {
45860          return lists.contains([
45861              KEY_MAP.LEFT,
45862              KEY_MAP.UP,
45863              KEY_MAP.RIGHT,
45864              KEY_MAP.DOWN,
45865          ], keyCode);
45866      },
45867      /**
45868       * @property {Object} nameFromCode
45869       * @property {String} nameFromCode.8 "BACKSPACE"
45870       */
45871      nameFromCode: func.invertObject(KEY_MAP),
45872      code: KEY_MAP
45873  };
45874
45875  /**
45876   * @method readFileAsDataURL
45877   *
45878   * read contents of file as representing URL
45879   *
45880   * @param {File} file
45881   * @return {Promise} - then: dataUrl
45882   */
45883  function readFileAsDataURL(file) {
45884      return $$1.Deferred(function (deferred) {
45885          $$1.extend(new FileReader(), {
45886              onload: function (e) {
45887                  var dataURL = e.target.result;
45888                  deferred.resolve(dataURL);
45889              },
45890              onerror: function (err) {
45891                  deferred.reject(err);
45892              }
45893          }).readAsDataURL(file);
45894      }).promise();
45895  }
45896  /**
45897   * @method createImage
45898   *
45899   * create `<image>` from url string
45900   *
45901   * @param {String} url
45902   * @return {Promise} - then: $image
45903   */
45904  function createImage(url) {
45905      return $$1.Deferred(function (deferred) {
45906          var $img = $$1('<img>');
45907          $img.one('load', function () {
45908              $img.off('error abort');
45909              deferred.resolve($img);
45910          }).one('error abort', function () {
45911              $img.off('load').detach();
45912              deferred.reject($img);
45913          }).css({
45914              display: 'none'
45915          }).appendTo(document.body).attr('src', url);
45916      }).promise();
45917  }
45918
45919  var History = /** @class */ (function () {
45920      function History($editable) {
45921          this.stack = [];
45922          this.stackOffset = -1;
45923          this.$editable = $editable;
45924          this.editable = $editable[0];
45925      }
45926      History.prototype.makeSnapshot = function () {
45927          var rng = range.create(this.editable);
45928          var emptyBookmark = { s: { path: [], offset: 0 }, e: { path: [], offset: 0 } };
45929          return {
45930              contents: this.$editable.html(),
45931              bookmark: ((rng && rng.isOnEditable()) ? rng.bookmark(this.editable) : emptyBookmark)
45932          };
45933      };
45934      History.prototype.applySnapshot = function (snapshot) {
45935          if (snapshot.contents !== null) {
45936              this.$editable.html(snapshot.contents);
45937          }
45938          if (snapshot.bookmark !== null) {
45939              range.createFromBookmark(this.editable, snapshot.bookmark).select();
45940          }
45941      };
45942      /**
45943      * @method rewind
45944      * Rewinds the history stack back to the first snapshot taken.
45945      * Leaves the stack intact, so that "Redo" can still be used.
45946      */
45947      History.prototype.rewind = function () {
45948          // Create snap shot if not yet recorded
45949          if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
45950              this.recordUndo();
45951          }
45952          // Return to the first available snapshot.
45953          this.stackOffset = 0;
45954          // Apply that snapshot.
45955          this.applySnapshot(this.stack[this.stackOffset]);
45956      };
45957      /**
45958      *  @method commit
45959      *  Resets history stack, but keeps current editor's content.
45960      */
45961      History.prototype.commit = function () {
45962          // Clear the stack.
45963          this.stack = [];
45964          // Restore stackOffset to its original value.
45965          this.stackOffset = -1;
45966          // Record our first snapshot (of nothing).
45967          this.recordUndo();
45968      };
45969      /**
45970      * @method reset
45971      * Resets the history stack completely; reverting to an empty editor.
45972      */
45973      History.prototype.reset = function () {
45974          // Clear the stack.
45975          this.stack = [];
45976          // Restore stackOffset to its original value.
45977          this.stackOffset = -1;
45978          // Clear the editable area.
45979          this.$editable.html('');
45980          // Record our first snapshot (of nothing).
45981          this.recordUndo();
45982      };
45983      /**
45984       * undo
45985       */
45986      History.prototype.undo = function () {
45987          // Create snap shot if not yet recorded
45988          if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
45989              this.recordUndo();
45990          }
45991          if (this.stackOffset > 0) {
45992              this.stackOffset--;
45993              this.applySnapshot(this.stack[this.stackOffset]);
45994          }
45995      };
45996      /**
45997       * redo
45998       */
45999      History.prototype.redo = function () {
46000          if (this.stack.length - 1 > this.stackOffset) {
46001              this.stackOffset++;
46002              this.applySnapshot(this.stack[this.stackOffset]);
46003          }
46004      };
46005      /**
46006       * recorded undo
46007       */
46008      History.prototype.recordUndo = function () {
46009          this.stackOffset++;
46010          // Wash out stack after stackOffset
46011          if (this.stack.length > this.stackOffset) {
46012              this.stack = this.stack.slice(0, this.stackOffset);
46013          }
46014          // Create new snapshot and push it to the end
46015          this.stack.push(this.makeSnapshot());
46016      };
46017      return History;
46018  }());
46019
46020  var Style = /** @class */ (function () {
46021      function Style() {
46022      }
46023      /**
46024       * @method jQueryCSS
46025       *
46026       * [workaround] for old jQuery
46027       * passing an array of style properties to .css()
46028       * will result in an object of property-value pairs.
46029       * (compability with version < 1.9)
46030       *
46031       * @private
46032       * @param  {jQuery} $obj
46033       * @param  {Array} propertyNames - An array of one or more CSS properties.
46034       * @return {Object}
46035       */
46036      Style.prototype.jQueryCSS = function ($obj, propertyNames) {
46037          if (env.jqueryVersion < 1.9) {
46038              var result_1 = {};
46039              $$1.each(propertyNames, function (idx, propertyName) {
46040                  result_1[propertyName] = $obj.css(propertyName);
46041              });
46042              return result_1;
46043          }
46044          return $obj.css(propertyNames);
46045      };
46046      /**
46047       * returns style object from node
46048       *
46049       * @param {jQuery} $node
46050       * @return {Object}
46051       */
46052      Style.prototype.fromNode = function ($node) {
46053          var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height'];
46054          var styleInfo = this.jQueryCSS($node, properties) || {};
46055          styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10);
46056          return styleInfo;
46057      };
46058      /**
46059       * paragraph level style
46060       *
46061       * @param {WrappedRange} rng
46062       * @param {Object} styleInfo
46063       */
46064      Style.prototype.stylePara = function (rng, styleInfo) {
vendor: 4,328 bytes, lines 46065-46157
46065          $$1.each(rng.nodes(dom.isPara, {
46066              includeAncestor: true
46067          }), function (idx, para) {
46068              $$1(para).css(styleInfo);
46069          });
46070      };
46071      /**
46072       * insert and returns styleNodes on range.
46073       *
46074       * @param {WrappedRange} rng
46075       * @param {Object} [options] - options for styleNodes
46076       * @param {String} [options.nodeName] - default: `SPAN`
46077       * @param {Boolean} [options.expandClosestSibling] - default: `false`
46078       * @param {Boolean} [options.onlyPartialContains] - default: `false`
46079       * @return {Node[]}
46080       */
46081      Style.prototype.styleNodes = function (rng, options) {
46082          rng = rng.splitText();
46083          var nodeName = (options && options.nodeName) || 'SPAN';
46084          var expandClosestSibling = !!(options && options.expandClosestSibling);
46085          var onlyPartialContains = !!(options && options.onlyPartialContains);
46086          if (rng.isCollapsed()) {
46087              return [rng.insertNode(dom.create(nodeName))];
46088          }
46089          var pred = dom.makePredByNodeName(nodeName);
46090          var nodes = rng.nodes(dom.isText, {
46091              fullyContains: true
46092          }).map(function (text) {
46093              return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName);
46094          });
46095          if (expandClosestSibling) {
46096              if (onlyPartialContains) {
46097                  var nodesInRange_1 = rng.nodes();
46098                  // compose with partial contains predication
46099                  pred = func.and(pred, function (node) {
46100                      return lists.contains(nodesInRange_1, node);
46101                  });
46102              }
46103              return nodes.map(function (node) {
46104                  var siblings = dom.withClosestSiblings(node, pred);
46105                  var head = lists.head(siblings);
46106                  var tails = lists.tail(siblings);
46107                  $$1.each(tails, function (idx, elem) {
46108                      dom.appendChildNodes(head, elem.childNodes);
46109                      dom.remove(elem);
46110                  });
46111                  return lists.head(siblings);
46112              });
46113          }
46114          else {
46115              return nodes;
46116          }
46117      };
46118      /**
46119       * get current style on cursor
46120       *
46121       * @param {WrappedRange} rng
46122       * @return {Object} - object contains style properties.
46123       */
46124      Style.prototype.current = function (rng) {
46125          var $cont = $$1(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc);
46126          var styleInfo = this.fromNode($cont);
46127          // document.queryCommandState for toggle state
46128          // [workaround] prevent Firefox nsresult: "0x80004005 (NS_ERROR_FAILURE)"
46129          try {
46130              styleInfo = $$1.extend(styleInfo, {
46131                  'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal',
46132                  'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal',
46133                  'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal',
46134                  'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal',
46135                  'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal',
46136                  'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal',
46137                  'font-family': document.queryCommandValue('fontname') || styleInfo['font-family']
46138              });
46139          }
46140          catch (e) { }
46141          // list-style-type to list-style(unordered, ordered)
46142          if (!rng.isOnList()) {
46143              styleInfo['list-style'] = 'none';
46144          }
46145          else {
46146              var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square'];
46147              var isUnordered = orderedTypes.indexOf(styleInfo['list-style-type']) > -1;
46148              styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered';
46149          }
46150          var para = dom.ancestor(rng.sc, dom.isPara);
46151          if (para && para.style['line-height']) {
46152              styleInfo['line-height'] = para.style.lineHeight;
46153          }
46154          else {
46155              var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10);
46156              styleInfo['line-height'] = lineHeight.toFixed(1);
46157          }
46158          styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor);
46159          styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable);
46160          styleInfo.range = rng;
46161          return styleInfo;
46162      };
46163      return Style;
46164  }());
46165
46166  var Bullet = /** @class */ (function () {
46167      function Bullet() {
46168      }
46169      /**
46170       * toggle ordered list
46171       */
46172      Bullet.prototype.insertOrderedList = function (editable) {
46173          this.toggleList('OL', editable);
46174      };
46175      /**
46176       * toggle unordered list
46177       */
46178      Bullet.prototype.insertUnorderedList = function (editable) {
46179          this.toggleList('UL', editable);
46180      };
46181      /**
46182       * indent
46183       */
46184      Bullet.prototype.indent = function (editable) {
46185          var _this = this;
46186          var rng = range.create(editable).wrapBodyInlineWithPara();
46187          var paras = rng.nodes(dom.isPara, { includeAncestor: true });
46188          var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
46189          $$1.each(clustereds, function (idx, paras) {
46190              var head = lists.head(paras);
46191              if (dom.isLi(head)) {
46192                  var previousList_1 = _this.findList(head.previousSibling);
46193                  if (previousList_1) {
46194                      paras
46195                          .map(function (para) { return previousList_1.appendChild(para); });
46196                  }
46197                  else {
46198                      _this.wrapList(paras, head.parentNode.nodeName);
46199                      paras
46200                          .map(function (para) { return para.parentNode; })
46201                          .map(function (para) { return _this.appendToPrevious(para); });
46202                  }
46203              }
46204              else {
46205                  $$1.each(paras, function (idx, para) {
46206                      $$1(para).css('marginLeft', function (idx, val) {
46207                          return (parseInt(val, 10) || 0) + 25;
46208                      });
46209                  });
46210              }
46211          });
46212          rng.select();
46213      };
46214      /**
46215       * outdent
46216       */
46217      Bullet.prototype.outdent = function (editable) {
46218          var _this = this;
46219          var rng = range.create(editable).wrapBodyInlineWithPara();
46220          var paras = rng.nodes(dom.isPara, { includeAncestor: true });
46221          var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
46222          $$1.each(clustereds, function (idx, paras) {
46223              var head = lists.head(paras);
46224              if (dom.isLi(head)) {
46225                  _this.releaseList([paras]);
46226              }
46227              else {
46228                  $$1.each(paras, function (idx, para) {
46229                      $$1(para).css('marginLeft', function (idx, val) {
46230                          val = (parseInt(val, 10) || 0);
46231                          return val > 25 ? val - 25 : '';
46232                      });
46233                  });
46234              }
46235          });
46236          rng.select();
46237      };
46238      /**
46239       * toggle list
46240       *
46241       * @param {String} listName - OL or UL
46242       */
46243      Bullet.prototype.toggleList = function (listName, editable) {
46244          var _this = this;
46245          var rng = range.create(editable).wrapBodyInlineWithPara();
46246          var paras = rng.nodes(dom.isPara, { includeAncestor: true });
46247          var bookmark = rng.paraBookmark(paras);
46248          var clustereds = lists.clusterBy(paras, func.peq2('parentNode'));
46249          // paragraph to list
46250          if (lists.find(paras, dom.isPurePara)) {
46251              var wrappedParas_1 = [];
46252              $$1.each(clustereds, function (idx, paras) {
46253                  wrappedParas_1 = wrappedParas_1.concat(_this.wrapList(paras, listName));
46254              });
46255              paras = wrappedParas_1;
46256              // list to paragraph or change list style
46257          }
46258          else {
46259              var diffLists = rng.nodes(dom.isList, {
46260                  includeAncestor: true
46261              }).filter(function (listNode) {
46262                  return !$$1.nodeName(listNode, listName);
46263              });
46264              if (diffLists.length) {
46265                  $$1.each(diffLists, function (idx, listNode) {
46266                      dom.replace(listNode, listName);
46267                  });
46268              }
46269              else {
46270                  paras = this.releaseList(clustereds, true);
46271              }
46272          }
46273          range.createFromParaBookmark(bookmark, paras).select();
46274      };
46275      /**
46276       * @param {Node[]} paras
46277       * @param {String} listName
46278       * @return {Node[]}
46279       */
46280      Bullet.prototype.wrapList = function (paras, listName) {
46281          var head = lists.head(paras);
46282          var last = lists.last(paras);
46283          var prevList = dom.isList(head.previousSibling) && head.previousSibling;
46284          var nextList = dom.isList(last.nextSibling) && last.nextSibling;
vendor: 18,288 bytes, lines 46285-46719
46285          var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last);
46286          // P to LI
46287          paras = paras.map(function (para) {
46288              return dom.isPurePara(para) ? dom.replace(para, 'LI') : para;
46289          });
46290          // append to list(<ul>, <ol>)
46291          dom.appendChildNodes(listNode, paras);
46292          if (nextList) {
46293              dom.appendChildNodes(listNode, lists.from(nextList.childNodes));
46294              dom.remove(nextList);
46295          }
46296          return paras;
46297      };
46298      /**
46299       * @method releaseList
46300       *
46301       * @param {Array[]} clustereds
46302       * @param {Boolean} isEscapseToBody
46303       * @return {Node[]}
46304       */
46305      Bullet.prototype.releaseList = function (clustereds, isEscapseToBody) {
46306          var _this = this;
46307          var releasedParas = [];
46308          $$1.each(clustereds, function (idx, paras) {
46309              var head = lists.head(paras);
46310              var last = lists.last(paras);
46311              var headList = isEscapseToBody ? dom.lastAncestor(head, dom.isList) : head.parentNode;
46312              var parentItem = headList.parentNode;
46313              if (headList.parentNode.nodeName === 'LI') {
46314                  paras.map(function (para) {
46315                      var newList = _this.findNextSiblings(para);
46316                      if (parentItem.nextSibling) {
46317                          parentItem.parentNode.insertBefore(para, parentItem.nextSibling);
46318                      }
46319                      else {
46320                          parentItem.parentNode.appendChild(para);
46321                      }
46322                      if (newList.length) {
46323                          _this.wrapList(newList, headList.nodeName);
46324                          para.appendChild(newList[0].parentNode);
46325                      }
46326                  });
46327                  if (headList.children.length === 0) {
46328                      parentItem.removeChild(headList);
46329                  }
46330                  if (parentItem.childNodes.length === 0) {
46331                      parentItem.parentNode.removeChild(parentItem);
46332                  }
46333              }
46334              else {
46335                  var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, {
46336                      node: last.parentNode,
46337                      offset: dom.position(last) + 1
46338                  }, {
46339                      isSkipPaddingBlankHTML: true
46340                  }) : null;
46341                  var middleList = dom.splitTree(headList, {
46342                      node: head.parentNode,
46343                      offset: dom.position(head)
46344                  }, {
46345                      isSkipPaddingBlankHTML: true
46346                  });
46347                  paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi)
46348                      : lists.from(middleList.childNodes).filter(dom.isLi);
46349                  // LI to P
46350                  if (isEscapseToBody || !dom.isList(headList.parentNode)) {
46351                      paras = paras.map(function (para) {
46352                          return dom.replace(para, 'P');
46353                      });
46354                  }
46355                  $$1.each(lists.from(paras).reverse(), function (idx, para) {
46356                      dom.insertAfter(para, headList);
46357                  });
46358                  // remove empty lists
46359                  var rootLists = lists.compact([headList, middleList, lastList]);
46360                  $$1.each(rootLists, function (idx, rootList) {
46361                      var listNodes = [rootList].concat(dom.listDescendant(rootList, dom.isList));
46362                      $$1.each(listNodes.reverse(), function (idx, listNode) {
46363                          if (!dom.nodeLength(listNode)) {
46364                              dom.remove(listNode, true);
46365                          }
46366                      });
46367                  });
46368              }
46369              releasedParas = releasedParas.concat(paras);
46370          });
46371          return releasedParas;
46372      };
46373      /**
46374       * @method appendToPrevious
46375       *
46376       * Appends list to previous list item, if
46377       * none exist it wraps the list in a new list item.
46378       *
46379       * @param {HTMLNode} ListItem
46380       * @return {HTMLNode}
46381       */
46382      Bullet.prototype.appendToPrevious = function (node) {
46383          return node.previousSibling
46384              ? dom.appendChildNodes(node.previousSibling, [node])
46385              : this.wrapList([node], 'LI');
46386      };
46387      /**
46388       * @method findList
46389       *
46390       * Finds an existing list in list item
46391       *
46392       * @param {HTMLNode} ListItem
46393       * @return {Array[]}
46394       */
46395      Bullet.prototype.findList = function (node) {
46396          return node
46397              ? lists.find(node.children, function (child) { return ['OL', 'UL'].indexOf(child.nodeName) > -1; })
46398              : null;
46399      };
46400      /**
46401       * @method findNextSiblings
46402       *
46403       * Finds all list item siblings that follow it
46404       *
46405       * @param {HTMLNode} ListItem
46406       * @return {HTMLNode}
46407       */
46408      Bullet.prototype.findNextSiblings = function (node) {
46409          var siblings = [];
46410          while (node.nextSibling) {
46411              siblings.push(node.nextSibling);
46412              node = node.nextSibling;
46413          }
46414          return siblings;
46415      };
46416      return Bullet;
46417  }());
46418
46419  /**
46420   * @class editing.Typing
46421   *
46422   * Typing
46423   *
46424   */
46425  var Typing = /** @class */ (function () {
46426      function Typing(context) {
46427          // a Bullet instance to toggle lists off
46428          this.bullet = new Bullet();
46429          this.options = context.options;
46430      }
46431      /**
46432       * insert tab
46433       *
46434       * @param {WrappedRange} rng
46435       * @param {Number} tabsize
46436       */
46437      Typing.prototype.insertTab = function (rng, tabsize) {
46438          var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR));
46439          rng = rng.deleteContents();
46440          rng.insertNode(tab, true);
46441          rng = range.create(tab, tabsize);
46442          rng.select();
46443      };
46444      /**
46445       * insert paragraph
46446       *
46447       * @param {jQuery} $editable
46448       * @param {WrappedRange} rng Can be used in unit tests to "mock" the range
46449       *
46450       * blockquoteBreakingLevel
46451       *   0 - No break, the new paragraph remains inside the quote
46452       *   1 - Break the first blockquote in the ancestors list
46453       *   2 - Break all blockquotes, so that the new paragraph is not quoted (this is the default)
46454       */
46455      Typing.prototype.insertParagraph = function (editable, rng) {
46456          rng = rng || range.create(editable);
46457          // deleteContents on range.
46458          rng = rng.deleteContents();
46459          // Wrap range if it needs to be wrapped by paragraph
46460          rng = rng.wrapBodyInlineWithPara();
46461          // finding paragraph
46462          var splitRoot = dom.ancestor(rng.sc, dom.isPara);
46463          var nextPara;
46464          // on paragraph: split paragraph
46465          if (splitRoot) {
46466              // if it is an empty line with li
46467              if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) {
46468                  // toogle UL/OL and escape
46469                  this.bullet.toggleList(splitRoot.parentNode.nodeName);
46470                  return;
46471              }
46472              else {
46473                  var blockquote = null;
46474                  if (this.options.blockquoteBreakingLevel === 1) {
46475                      blockquote = dom.ancestor(splitRoot, dom.isBlockquote);
46476                  }
46477                  else if (this.options.blockquoteBreakingLevel === 2) {
46478                      blockquote = dom.lastAncestor(splitRoot, dom.isBlockquote);
46479                  }
46480                  if (blockquote) {
46481                      // We're inside a blockquote and options ask us to break it
46482                      nextPara = $$1(dom.emptyPara)[0];
46483                      // If the split is right before a <br>, remove it so that there's no "empty line"
46484                      // after the split in the new blockquote created
46485                      if (dom.isRightEdgePoint(rng.getStartPoint()) && dom.isBR(rng.sc.nextSibling)) {
46486                          $$1(rng.sc.nextSibling).remove();
46487                      }
46488                      var split = dom.splitTree(blockquote, rng.getStartPoint(), { isDiscardEmptySplits: true });
46489                      if (split) {
46490                          split.parentNode.insertBefore(nextPara, split);
46491                      }
46492                      else {
46493                          dom.insertAfter(nextPara, blockquote); // There's no split if we were at the end of the blockquote
46494                      }
46495                  }
46496                  else {
46497                      nextPara = dom.splitTree(splitRoot, rng.getStartPoint());
46498                      // not a blockquote, just insert the paragraph
46499                      var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor);
46500                      emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor));
46501                      $$1.each(emptyAnchors, function (idx, anchor) {
46502                          dom.remove(anchor);
46503                      });
46504                      // replace empty heading, pre or custom-made styleTag with P tag
46505                      if ((dom.isHeading(nextPara) || dom.isPre(nextPara) || dom.isCustomStyleTag(nextPara)) && dom.isEmpty(nextPara)) {
46506                          nextPara = dom.replace(nextPara, 'p');
46507                      }
46508                  }
46509              }
46510              // no paragraph: insert empty paragraph
46511          }
46512          else {
46513              var next = rng.sc.childNodes[rng.so];
46514              nextPara = $$1(dom.emptyPara)[0];
46515              if (next) {
46516                  rng.sc.insertBefore(nextPara, next);
46517              }
46518              else {
46519                  rng.sc.appendChild(nextPara);
46520              }
46521          }
46522          range.create(nextPara, 0).normalize().select().scrollIntoView(editable);
46523      };
46524      return Typing;
46525  }());
46526
46527  /**
46528   * @class Create a virtual table to create what actions to do in change.
46529   * @param {object} startPoint Cell selected to apply change.
46530   * @param {enum} where  Where change will be applied Row or Col. Use enum: TableResultAction.where
46531   * @param {enum} action Action to be applied. Use enum: TableResultAction.requestAction
46532   * @param {object} domTable Dom element of table to make changes.
46533   */
46534  var TableResultAction = function (startPoint, where, action, domTable) {
46535      var _startPoint = { 'colPos': 0, 'rowPos': 0 };
46536      var _virtualTable = [];
46537      var _actionCellList = [];
46538      /// ///////////////////////////////////////////
46539      // Private functions
46540      /// ///////////////////////////////////////////
46541      /**
46542       * Set the startPoint of action.
46543       */
46544      function setStartPoint() {
46545          if (!startPoint || !startPoint.tagName || (startPoint.tagName.toLowerCase() !== 'td' && startPoint.tagName.toLowerCase() !== 'th')) {
46546              console.error('Impossible to identify start Cell point.', startPoint);
46547              return;
46548          }
46549          _startPoint.colPos = startPoint.cellIndex;
46550          if (!startPoint.parentElement || !startPoint.parentElement.tagName || startPoint.parentElement.tagName.toLowerCase() !== 'tr') {
46551              console.error('Impossible to identify start Row point.', startPoint);
46552              return;
46553          }
46554          _startPoint.rowPos = startPoint.parentElement.rowIndex;
46555      }
46556      /**
46557       * Define virtual table position info object.
46558       *
46559       * @param {int} rowIndex Index position in line of virtual table.
46560       * @param {int} cellIndex Index position in column of virtual table.
46561       * @param {object} baseRow Row affected by this position.
46562       * @param {object} baseCell Cell affected by this position.
46563       * @param {bool} isSpan Inform if it is an span cell/row.
46564       */
46565      function setVirtualTablePosition(rowIndex, cellIndex, baseRow, baseCell, isRowSpan, isColSpan, isVirtualCell) {
46566          var objPosition = {
46567              'baseRow': baseRow,
46568              'baseCell': baseCell,
46569              'isRowSpan': isRowSpan,
46570              'isColSpan': isColSpan,
46571              'isVirtual': isVirtualCell
46572          };
46573          if (!_virtualTable[rowIndex]) {
46574              _virtualTable[rowIndex] = [];
46575          }
46576          _virtualTable[rowIndex][cellIndex] = objPosition;
46577      }
46578      /**
46579       * Create action cell object.
46580       *
46581       * @param {object} virtualTableCellObj Object of specific position on virtual table.
46582       * @param {enum} resultAction Action to be applied in that item.
46583       */
46584      function getActionCell(virtualTableCellObj, resultAction, virtualRowPosition, virtualColPosition) {
46585          return {
46586              'baseCell': virtualTableCellObj.baseCell,
46587              'action': resultAction,
46588              'virtualTable': {
46589                  'rowIndex': virtualRowPosition,
46590                  'cellIndex': virtualColPosition
46591              }
46592          };
46593      }
46594      /**
46595       * Recover free index of row to append Cell.
46596       *
46597       * @param {int} rowIndex Index of row to find free space.
46598       * @param {int} cellIndex Index of cell to find free space in table.
46599       */
46600      function recoverCellIndex(rowIndex, cellIndex) {
46601          if (!_virtualTable[rowIndex]) {
46602              return cellIndex;
46603          }
46604          if (!_virtualTable[rowIndex][cellIndex]) {
46605              return cellIndex;
46606          }
46607          var newCellIndex = cellIndex;
46608          while (_virtualTable[rowIndex][newCellIndex]) {
46609              newCellIndex++;
46610              if (!_virtualTable[rowIndex][newCellIndex]) {
46611                  return newCellIndex;
46612              }
46613          }
46614      }
46615      /**
46616       * Recover info about row and cell and add information to virtual table.
46617       *
46618       * @param {object} row Row to recover information.
46619       * @param {object} cell Cell to recover information.
46620       */
46621      function addCellInfoToVirtual(row, cell) {
46622          var cellIndex = recoverCellIndex(row.rowIndex, cell.cellIndex);
46623          var cellHasColspan = (cell.colSpan > 1);
46624          var cellHasRowspan = (cell.rowSpan > 1);
46625          var isThisSelectedCell = (row.rowIndex === _startPoint.rowPos && cell.cellIndex === _startPoint.colPos);
46626          setVirtualTablePosition(row.rowIndex, cellIndex, row, cell, cellHasRowspan, cellHasColspan, false);
46627          // Add span rows to virtual Table.
46628          var rowspanNumber = cell.attributes.rowSpan ? parseInt(cell.attributes.rowSpan.value, 10) : 0;
46629          if (rowspanNumber > 1) {
46630              for (var rp = 1; rp < rowspanNumber; rp++) {
46631                  var rowspanIndex = row.rowIndex + rp;
46632                  adjustStartPoint(rowspanIndex, cellIndex, cell, isThisSelectedCell);
46633                  setVirtualTablePosition(rowspanIndex, cellIndex, row, cell, true, cellHasColspan, true);
46634              }
46635          }
46636          // Add span cols to virtual table.
46637          var colspanNumber = cell.attributes.colSpan ? parseInt(cell.attributes.colSpan.value, 10) : 0;
46638          if (colspanNumber > 1) {
46639              for (var cp = 1; cp < colspanNumber; cp++) {
46640                  var cellspanIndex = recoverCellIndex(row.rowIndex, (cellIndex + cp));
46641                  adjustStartPoint(row.rowIndex, cellspanIndex, cell, isThisSelectedCell);
46642                  setVirtualTablePosition(row.rowIndex, cellspanIndex, row, cell, cellHasRowspan, true, true);
46643              }
46644          }
46645      }
46646      /**
46647       * Process validation and adjust of start point if needed
46648       *
46649       * @param {int} rowIndex
46650       * @param {int} cellIndex
46651       * @param {object} cell
46652       * @param {bool} isSelectedCell
46653       */
46654      function adjustStartPoint(rowIndex, cellIndex, cell, isSelectedCell) {
46655          if (rowIndex === _startPoint.rowPos && _startPoint.colPos >= cell.cellIndex && cell.cellIndex <= cellIndex && !isSelectedCell) {
46656              _startPoint.colPos++;
46657          }
46658      }
46659      /**
46660       * Create virtual table of cells with all cells, including span cells.
46661       */
46662      function createVirtualTable() {
46663          var rows = domTable.rows;
46664          for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
46665              var cells = rows[rowIndex].cells;
46666              for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {
46667                  addCellInfoToVirtual(rows[rowIndex], cells[cellIndex]);
46668              }
46669          }
46670      }
46671      /**
46672       * Get action to be applied on the cell.
46673       *
46674       * @param {object} cell virtual table cell to apply action
46675       */
46676      function getDeleteResultActionToCell(cell) {
46677          switch (where) {
46678              case TableResultAction.where.Column:
46679                  if (cell.isColSpan) {
46680                      return TableResultAction.resultAction.SubtractSpanCount;
46681                  }
46682                  break;
46683              case TableResultAction.where.Row:
46684                  if (!cell.isVirtual && cell.isRowSpan) {
46685                      return TableResultAction.resultAction.AddCell;
46686                  }
46687                  else if (cell.isRowSpan) {
46688                      return TableResultAction.resultAction.SubtractSpanCount;
46689                  }
46690                  break;
46691          }
46692          return TableResultAction.resultAction.RemoveCell;
46693      }
46694      /**
46695       * Get action to be applied on the cell.
46696       *
46697       * @param {object} cell virtual table cell to apply action
46698       */
46699      function getAddResultActionToCell(cell) {
46700          switch (where) {
46701              case TableResultAction.where.Column:
46702                  if (cell.isColSpan) {
46703                      return TableResultAction.resultAction.SumSpanCount;
46704                  }
46705                  else if (cell.isRowSpan && cell.isVirtual) {
46706                      return TableResultAction.resultAction.Ignore;
46707                  }
46708                  break;
46709              case TableResultAction.where.Row:
46710                  if (cell.isRowSpan) {
46711                      return TableResultAction.resultAction.SumSpanCount;
46712                  }
46713                  else if (cell.isColSpan && cell.isVirtual) {
46714                      return TableResultAction.resultAction.Ignore;
46715                  }
46716                  break;
46717          }
46718          return TableResultAction.resultAction.AddCell;
46719      }
46720      function init() {
46721          setStartPoint();
46722          createVirtualTable();
46723      }
46724      /// ///////////////////////////////////////////
46725      // Public functions
46726      /// ///////////////////////////////////////////
46727      /**
46728       * Recover array os what to do in table.
46729       */
46730      this.getActionList = function () {
46731          var fixedRow = (where === TableResultAction.where.Row) ? _startPoint.rowPos : -1;
46732          var fixedCol = (where === TableResultAction.where.Column) ? _startPoint.colPos : -1;
46733          var actualPosition = 0;
46734          var canContinue = true;
46735          while (canContinue) {
46736              var rowPosition = (fixedRow >= 0) ? fixedRow : actualPosition;
46737              var colPosition = (fixedCol >= 0) ? fixedCol : actualPosition;
46738              var row = _virtualTable[rowPosition];
46739              if (!row) {
46740                  canContinue = false;
46741                  return _actionCellList;
46742              }
46743              var cell = row[colPosition];
46744              if (!cell) {
46745                  canContinue = false;
46746                  return _actionCellList;
46747              }
46748              // Define action to be applied in this cell
46749              var resultAction = TableResultAction.resultAction.Ignore;
46750              switch (action) {
46751                  case TableResultAction.requestAction.Add:
46752                      resultAction = getAddResultActionToCell(cell);
46753                      break;
46754                  case TableResultAction.requestAction.Delete:
46755                      resultAction = getDeleteResultActionToCell(cell);
46756                      break;
46757              }
46758              _actionCellList.push(getActionCell(cell, resultAction, rowPosition, colPosition));
46759              actualPosition++;
46760          }
46761          return _actionCellList;
46762      };
46763      init();
46764  };
46765  /**
46766  *
46767  * Where action occours enum.
46768  */
46769  TableResultAction.where = { 'Row': 0, 'Column': 1 };
46770  /**
46771  *
46772  * Requested action to apply enum.
46773  */
46774  TableResultAction.requestAction = { 'Add': 0, 'Delete': 1 };
46775  /**
46776  *
46777  * Result action to be executed enum.
46778  */
46779  TableResultAction.resultAction = { 'Ignore': 0, 'SubtractSpanCount': 1, 'RemoveCell': 2, 'AddCell': 3, 'SumSpanCount': 4 };
46780  /**
46781   *
46782   * @class editing.Table
46783   *
46784   * Table
46785   *
46786   */
46787  var Table = /** @class */ (function () {
46788      function Table() {
46789      }
46790      /**
46791       * handle tab key
46792       *
46793       * @param {WrappedRange} rng
46794       * @param {Boolean} isShift
46795       */
46796      Table.prototype.tab = function (rng, isShift) {
46797          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
46798          var table = dom.ancestor(cell, dom.isTable);
46799          var cells = dom.listDescendant(table, dom.isCell);
46800          var nextCell = lists[isShift ? 'prev' : 'next'](cells, cell);
46801          if (nextCell) {
46802              range.create(nextCell, 0).select();
46803          }
46804      };
46805      /**
46806       * Add a new row
46807       *
46808       * @param {WrappedRange} rng
46809       * @param {String} position (top/bottom)
46810       * @return {Node}
46811       */
46812      Table.prototype.addRow = function (rng, position) {
46813          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
46814          var currentTr = $$1(cell).closest('tr');
46815          var trAttributes = this.recoverAttributes(currentTr);
46816          var html = $$1('<tr' + trAttributes + '></tr>');
46817          var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Add, $$1(currentTr).closest('table')[0]);
46818          var actions = vTable.getActionList();
46819          for (var idCell = 0; idCell < actions.length; idCell++) {
46820              var currentCell = actions[idCell];
46821              var tdAttributes = this.recoverAttributes(currentCell.baseCell);
46822              switch (currentCell.action) {
46823                  case TableResultAction.resultAction.AddCell:
46824                      html.append('<td' + tdAttributes + '>' + dom.blank + '</td>');
46825                      break;
46826                  case TableResultAction.resultAction.SumSpanCount:
46827                      if (position === 'top') {
46828                          var baseCellTr = currentCell.baseCell.parent;
46829                          var isTopFromRowSpan = (!baseCellTr ? 0 : currentCell.baseCell.closest('tr').rowIndex) <= currentTr[0].rowIndex;
46830                          if (isTopFromRowSpan) {
46831                              var newTd = $$1('<div></div>').append($$1('<td' + tdAttributes + '>' + dom.blank + '</td>').removeAttr('rowspan')).html();
46832                              html.append(newTd);
46833                              break;
46834                          }
46835                      }
46836                      var rowspanNumber = parseInt(currentCell.baseCell.rowSpan, 10);
46837                      rowspanNumber++;
46838                      currentCell.baseCell.setAttribute('rowSpan', rowspanNumber);
46839                      break;
46840              }
46841          }
46842          if (position === 'top') {
46843              currentTr.before(html);
46844          }
46845          else {
46846              var cellHasRowspan = (cell.rowSpan > 1);
46847              if (cellHasRowspan) {
46848                  var lastTrIndex = currentTr[0].rowIndex + (cell.rowSpan - 2);
46849                  $$1($$1(currentTr).parent().find('tr')[lastTrIndex]).after($$1(html));
46850                  return;
46851              }
46852              currentTr.after(html);
46853          }
46854      };
46855      /**
46856       * Add a new col
46857       *
46858       * @param {WrappedRange} rng
46859       * @param {String} position (left/right)
46860       * @return {Node}
46861       */
46862      Table.prototype.addCol = function (rng, position) {
46863          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
46864          var row = $$1(cell).closest('tr');
46865          var rowsGroup = $$1(row).siblings();
46866          rowsGroup.push(row);
46867          var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Add, $$1(row).closest('table')[0]);
46868          var actions = vTable.getActionList();
46869          for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
46870              var currentCell = actions[actionIndex];
46871              var tdAttributes = this.recoverAttributes(currentCell.baseCell);
46872              switch (currentCell.action) {
46873                  case TableResultAction.resultAction.AddCell:
46874                      if (position === 'right') {
46875                          $$1(currentCell.baseCell).after('<td' + tdAttributes + '>' + dom.blank + '</td>');
46876                      }
46877                      else {
46878                          $$1(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');
46879                      }
46880                      break;
46881                  case TableResultAction.resultAction.SumSpanCount:
46882                      if (position === 'right') {
46883                          var colspanNumber = parseInt(currentCell.baseCell.colSpan, 10);
46884                          colspanNumber++;
46885                          currentCell.baseCell.setAttribute('colSpan', colspanNumber);
46886                      }
46887                      else {
46888                          $$1(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>');
46889                      }
46890                      break;
46891              }
46892          }
46893      };
46894      /*
46895      * Copy attributes from element.
46896      *
46897      * @param {object} Element to recover attributes.
46898      * @return {string} Copied string elements.
46899      */
46900      Table.prototype.recoverAttributes = function (el) {
46901          var resultStr = '';
46902          if (!el) {
46903              return resultStr;
46904          }
46905          var attrList = el.attributes || [];
46906          for (var i = 0; i < attrList.length; i++) {
46907              if (attrList[i].name.toLowerCase() === 'id') {
46908                  continue;
46909              }
46910              if (attrList[i].specified) {
46911                  resultStr += ' ' + attrList[i].name + '=\'' + attrList[i].value + '\'';
46912              }
46913          }
46914          return resultStr;
46915      };
46916      /**
46917       * Delete current row
46918       *
46919       * @param {WrappedRange} rng
46920       * @return {Node}
46921       */
46922      Table.prototype.deleteRow = function (rng) {
46923          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
46924          var row = $$1(cell).closest('tr');
46925          var cellPos = row.children('td, th').index($$1(cell));
46926          var rowPos = row[0].rowIndex;
46927          var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Delete, $$1(row).closest('table')[0]);
46928          var actions = vTable.getActionList();
46929          for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
46930              if (!actions[actionIndex]) {
46931                  continue;
46932              }
46933              var baseCell = actions[actionIndex].baseCell;
46934              var virtualPosition = actions[actionIndex].virtualTable;
46935              var hasRowspan = (baseCell.rowSpan && baseCell.rowSpan > 1);
46936              var rowspanNumber = (hasRowspan) ? parseInt(baseCell.rowSpan, 10) : 0;
46937              switch (actions[actionIndex].action) {
46938                  case TableResultAction.resultAction.Ignore:
46939                      continue;
46940                  case TableResultAction.resultAction.AddCell:
46941                      var nextRow = row.next('tr')[0];
46942                      if (!nextRow) {
46943                          continue;
46944                      }
46945                      var cloneRow = row[0].cells[cellPos];
46946                      if (hasRowspan) {
46947                          if (rowspanNumber > 2) {
46948                              rowspanNumber--;
46949                              nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);
46950                              nextRow.cells[cellPos].setAttribute('rowSpan', rowspanNumber);
46951                              nextRow.cells[cellPos].innerHTML = '';
46952                          }
46953                          else if (rowspanNumber === 2) {
46954                              nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]);
46955                              nextRow.cells[cellPos].removeAttribute('rowSpan');
46956                              nextRow.cells[cellPos].innerHTML = '';
46957                          }
46958                      }
46959                      continue;
46960                  case TableResultAction.resultAction.SubtractSpanCount:
46961                      if (hasRowspan) {
46962                          if (rowspanNumber > 2) {
46963                              rowspanNumber--;
46964                              baseCell.setAttribute('rowSpan', rowspanNumber);
46965                              if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) {
46966                                  baseCell.innerHTML = '';
46967                              }
46968                          }
46969                          else if (rowspanNumber === 2) {
46970                              baseCell.removeAttribute('rowSpan');
46971                              if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) {
46972                                  baseCell.innerHTML = '';
46973                              }
46974                          }
46975                      }
46976                      continue;
46977                  case TableResultAction.resultAction.RemoveCell:
46978                      // Do not need remove cell because row will be deleted.
46979                      continue;
46980              }
46981          }
46982          row.remove();
46983      };
46984      /**
46985       * Delete current col
46986       *
46987       * @param {WrappedRange} rng
46988       * @return {Node}
46989       */
46990      Table.prototype.deleteCol = function (rng) {
46991          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
46992          var row = $$1(cell).closest('tr');
46993          var cellPos = row.children('td, th').index($$1(cell));
46994          var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Delete, $$1(row).closest('table')[0]);
46995          var actions = vTable.getActionList();
46996          for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) {
46997              if (!actions[actionIndex]) {
46998                  continue;
46999              }
47000              switch (actions[actionIndex].action) {
47001                  case TableResultAction.resultAction.Ignore:
47002                      continue;
47003                  case TableResultAction.resultAction.SubtractSpanCount:
47004                      var baseCell = actions[actionIndex].baseCell;
47005                      var hasColspan = (baseCell.colSpan && baseCell.colSpan > 1);
47006                      if (hasColspan) {
47007                          var colspanNumber = (baseCell.colSpan) ? parseInt(baseCell.colSpan, 10) : 0;
47008                          if (colspanNumber > 2) {
47009                              colspanNumber--;
47010                              baseCell.setAttribute('colSpan', colspanNumber);
47011                              if (baseCell.cellIndex === cellPos) {
47012                                  baseCell.innerHTML = '';
47013                              }
47014                          }
47015                          else if (colspanNumber === 2) {
47016                              baseCell.removeAttribute('colSpan');
47017                              if (baseCell.cellIndex === cellPos) {
47018                                  baseCell.innerHTML = '';
47019                              }
47020                          }
47021                      }
47022                      continue;
47023                  case TableResultAction.resultAction.RemoveCell:
47024                      dom.remove(actions[actionIndex].baseCell, true);
47025                      continue;
47026              }
47027          }
47028      };
47029      /**
47030       * create empty table element
47031       *
47032       * @param {Number} rowCount
47033       * @param {Number} colCount
47034       * @return {Node}
47035       */
47036      Table.prototype.createTable = function (colCount, rowCount, options) {
47037          var tds = [];
47038          var tdHTML;
47039          for (var idxCol = 0; idxCol < colCount; idxCol++) {
47040              tds.push('<td>' + dom.blank + '</td>');
47041          }
47042          tdHTML = tds.join('');
47043          var trs = [];
47044          var trHTML;
47045          for (var idxRow = 0; idxRow < rowCount; idxRow++) {
47046              trs.push('<tr>' + tdHTML + '</tr>');
47047          }
47048          trHTML = trs.join('');
47049          var $table = $$1('<table>' + trHTML + '</table>');
47050          if (options && options.tableClassName) {
47051              $table.addClass(options.tableClassName);
47052          }
47053          return $table[0];
47054      };
47055      /**
47056       * Delete current table
47057       *
47058       * @param {WrappedRange} rng
47059       * @return {Node}
47060       */
47061      Table.prototype.deleteTable = function (rng) {
47062          var cell = dom.ancestor(rng.commonAncestor(), dom.isCell);
47063          $$1(cell).closest('table').remove();
47064      };
47065      return Table;
47066  }());
47067
47068  var KEY_BOGUS = 'bogus';
47069  /**
47070   * @class Editor
47071   */
47072  var Editor = /** @class */ (function () {
47073      function Editor(context) {
47074          var _this = this;
47075          this.context = context;
47076          this.$note = context.layoutInfo.note;
47077          this.$editor = context.layoutInfo.editor;
47078          this.$editable = context.layoutInfo.editable;
47079          this.options = context.options;
47080          this.lang = this.options.langInfo;
47081          this.editable = this.$editable[0];
47082          this.lastRange = null;
47083          this.style = new Style();
47084          this.table = new Table();
47085          this.typing = new Typing(context);
47086          this.bullet = new Bullet();
47087          this.history = new History(this.$editable);
47088          this.context.memo('help.undo', this.lang.help.undo);
47089          this.context.memo('help.redo', this.lang.help.redo);
47090          this.context.memo('help.tab', this.lang.help.tab);
47091          this.context.memo('help.untab', this.lang.help.untab);
47092          this.context.memo('help.insertParagraph', this.lang.help.insertParagraph);
47093          this.context.memo('help.insertOrderedList', this.lang.help.insertOrderedList);
47094          this.context.memo('help.insertUnorderedList', this.lang.help.insertUnorderedList);
47095          this.context.memo('help.indent', this.lang.help.indent);
47096          this.context.memo('help.outdent', this.lang.help.outdent);
47097          this.context.memo('help.formatPara', this.lang.help.formatPara);
47098          this.context.memo('help.insertHorizontalRule', this.lang.help.insertHorizontalRule);
47099          this.context.memo('help.fontName', this.lang.help.fontName);
47100          // native commands(with execCommand), generate function for execCommand
47101          var commands = [
47102              'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript',
47103              'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull',
47104              'formatBlock', 'removeFormat', 'backColor',
47105          ];
47106          for (var idx = 0, len = commands.length; idx < len; idx++) {
47107              this[commands[idx]] = (function (sCmd) {
47108                  return function (value) {
47109                      _this.beforeCommand();
47110                      document.execCommand(sCmd, false, value);
47111                      _this.afterCommand(true);
47112                  };
47113              })(commands[idx]);
47114              this.context.memo('help.' + commands[idx], this.lang.help[commands[idx]]);
47115          }
47116          this.fontName = this.wrapCommand(function (value) {
47117              return _this.fontStyling('font-family', "\'" + value + "\'");
47118          });
47119          this.fontSize = this.wrapCommand(function (value) {
47120              return _this.fontStyling('font-size', value + 'px');
47121          });
47122          for (var idx = 1; idx <= 6; idx++) {
47123              this['formatH' + idx] = (function (idx) {
47124                  return function () {
47125                      _this.formatBlock('H' + idx);
47126                  };
47127              })(idx);
47128              this.context.memo('help.formatH' + idx, this.lang.help['formatH' + idx]);
47129          }
47130          this.insertParagraph = this.wrapCommand(function () {
47131              _this.typing.insertParagraph(_this.editable);
47132          });
47133          this.insertOrderedList = this.wrapCommand(function () {
47134              _this.bullet.insertOrderedList(_this.editable);
47135          });
47136          this.insertUnorderedList = this.wrapCommand(function () {
47137              _this.bullet.insertUnorderedList(_this.editable);
47138          });
47139          this.indent = this.wrapCommand(function () {
47140              _this.bullet.indent(_this.editable);
47141          });
47142          this.outdent = this.wrapCommand(function () {
47143              _this.bullet.outdent(_this.editable);
47144          });
47145          /**
vendor: 3,599 bytes, lines 47146-47240
47146           * insertNode
47147           * insert node
47148           * @param {Node} node
47149           */
47150          this.insertNode = this.wrapCommand(function (node) {
47151              if (_this.isLimited($$1(node).text().length)) {
47152                  return;
47153              }
47154              var rng = _this.getLastRange();
47155              rng.insertNode(node);
47156              range.createFromNodeAfter(node).select();
47157              _this.setLastRange();
47158          });
47159          /**
47160           * insert text
47161           * @param {String} text
47162           */
47163          this.insertText = this.wrapCommand(function (text) {
47164              if (_this.isLimited(text.length)) {
47165                  return;
47166              }
47167              var rng = _this.getLastRange();
47168              var textNode = rng.insertNode(dom.createText(text));
47169              range.create(textNode, dom.nodeLength(textNode)).select();
47170              _this.setLastRange();
47171          });
47172          /**
47173           * paste HTML
47174           * @param {String} markup
47175           */
47176          this.pasteHTML = this.wrapCommand(function (markup) {
47177              if (_this.isLimited(markup.length)) {
47178                  return;
47179              }
47180              markup = _this.context.invoke('codeview.purify', markup);
47181              var contents = _this.getLastRange().pasteHTML(markup);
47182              range.createFromNodeAfter(lists.last(contents)).select();
47183              _this.setLastRange();
47184          });
47185          /**
47186           * formatBlock
47187           *
47188           * @param {String} tagName
47189           */
47190          this.formatBlock = this.wrapCommand(function (tagName, $target) {
47191              var onApplyCustomStyle = _this.options.callbacks.onApplyCustomStyle;
47192              if (onApplyCustomStyle) {
47193                  onApplyCustomStyle.call(_this, $target, _this.context, _this.onFormatBlock);
47194              }
47195              else {
47196                  _this.onFormatBlock(tagName, $target);
47197              }
47198          });
47199          /**
47200           * insert horizontal rule
47201           */
47202          this.insertHorizontalRule = this.wrapCommand(function () {
47203              var hrNode = _this.getLastRange().insertNode(dom.create('HR'));
47204              if (hrNode.nextSibling) {
47205                  range.create(hrNode.nextSibling, 0).normalize().select();
47206                  _this.setLastRange();
47207              }
47208          });
47209          /**
47210           * lineHeight
47211           * @param {String} value
47212           */
47213          this.lineHeight = this.wrapCommand(function (value) {
47214              _this.style.stylePara(_this.getLastRange(), {
47215                  lineHeight: value
47216              });
47217          });
47218          /**
47219           * create link (command)
47220           *
47221           * @param {Object} linkInfo
47222           */
47223          this.createLink = this.wrapCommand(function (linkInfo) {
47224              var linkUrl = linkInfo.url;
47225              var linkText = linkInfo.text;
47226              var isNewWindow = linkInfo.isNewWindow;
47227              var rng = linkInfo.range || _this.getLastRange();
47228              var additionalTextLength = linkText.length - rng.toString().length;
47229              if (additionalTextLength > 0 && _this.isLimited(additionalTextLength)) {
47230                  return;
47231              }
47232              var isTextChanged = rng.toString() !== linkText;
47233              // handle spaced urls from input
47234              if (typeof linkUrl === 'string') {
47235                  linkUrl = linkUrl.trim();
47236              }
47237              if (_this.options.onCreateLink) {
47238                  linkUrl = _this.options.onCreateLink(linkUrl);
47239              }
47240              else {
47241                  // if url doesn't have any protocol and not even a relative or a label, use http:// as default
47242                  linkUrl = /^([A-Za-z][A-Za-z0-9+-.]*\:|#|\/)/.test(linkUrl)
47243                      ? linkUrl : 'http://' + linkUrl;
47244              }
47245              var anchors = [];
47246              if (isTextChanged) {
47247                  rng = rng.deleteContents();
47248                  var anchor = rng.insertNode($$1('<A>' + linkText + '</A>')[0]);
47249                  anchors.push(anchor);
47250              }
47251              else {
47252                  anchors = _this.style.styleNodes(rng, {
47253                      nodeName: 'A',
47254                      expandClosestSibling: true,
47255                      onlyPartialContains: true
47256                  });
47257              }
47258              $$1.each(anchors, function (idx, anchor) {
47259                  $$1(anchor).attr('href', linkUrl);
47260                  if (isNewWindow) {
47261                      $$1(anchor).attr('target', '_blank');
47262                  }
47263                  else {
47264                      $$1(anchor).removeAttr('target');
47265                  }
47266              });
47267              var startRange = range.createFromNodeBefore(lists.head(anchors));
47268              var startPoint = startRange.getStartPoint();
47269              var endRange = range.createFromNodeAfter(lists.last(anchors));
47270              var endPoint = endRange.getEndPoint();
47271              range.create(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset).select();
47272              _this.setLastRange();
47273          });
47274          /**
47275           * setting color
47276           *
47277           * @param {Object} sObjColor  color code
47278           * @param {String} sObjColor.foreColor foreground color
47279           * @param {String} sObjColor.backColor background color
47280           */
47281          this.color = this.wrapCommand(function (colorInfo) {
47282              var foreColor = colorInfo.foreColor;
47283              var backColor = colorInfo.backColor;
47284              if (foreColor) {
47285                  document.execCommand('foreColor', false, foreColor);
47286              }
47287              if (backColor) {
47288                  document.execCommand('backColor', false, backColor);
47289              }
47290          });
47291          /**
47292           * Set foreground color
47293           *
47294           * @param {String} colorCode foreground color code
47295           */
47296          this.foreColor = this.wrapCommand(function (colorInfo) {
47297              document.execCommand('styleWithCSS', false, true);
47298              document.execCommand('foreColor', false, colorInfo);
47299          });
47300          /**
47301           * insert Table
47302           *
47303           * @param {String} dimension of table (ex : "5x5")
47304           */
47305          this.insertTable = this.wrapCommand(function (dim) {
47306              var dimension = dim.split('x');
47307              var rng = _this.getLastRange().deleteContents();
47308              rng.insertNode(_this.table.createTable(dimension[0], dimension[1], _this.options));
47309          });
47310          /**
47311           * remove media object and Figure Elements if media object is img with Figure.
47312           */
47313          this.removeMedia = this.wrapCommand(function () {
47314              var $target = $$1(_this.restoreTarget()).parent();
47315              if ($target.parent('figure').length) {
47316                  $target.parent('figure').remove();
47317              }
47318              else {
47319                  $target = $$1(_this.restoreTarget()).detach();
47320              }
47321              _this.context.triggerEvent('media.delete', $target, _this.$editable);
47322          });
47323          /**
47324           * float me
47325           *
47326           * @param {String} value
47327           */
47328          this.floatMe = this.wrapCommand(function (value) {
47329              var $target = $$1(_this.restoreTarget());
47330              $target.toggleClass('note-float-left', value === 'left');
47331              $target.toggleClass('note-float-right', value === 'right');
47332              $target.css('float', (value === 'none' ? '' : value));
47333          });
47334          /**
47335           * resize overlay element
47336           * @param {String} value
47337           */
47338          this.resize = this.wrapCommand(function (value) {
47339              var $target = $$1(_this.restoreTarget());
47340              value = parseFloat(value);
47341              if (value === 0) {
47342                  $target.css('width', '');
47343              }
47344              else {
47345                  $target.css({
47346                      width: value * 100 + '%',
47347                      height: ''
47348                  });
47349              }
47350          });
47351      }
47352      Editor.prototype.initialize = function () {
47353          var _this = this;
47354          // bind custom events
47355          this.$editable.on('keydown', function (event) {
47356              if (event.keyCode === key.code.ENTER) {
47357                  _this.context.triggerEvent('enter', event);
47358              }
47359              _this.context.triggerEvent('keydown', event);
47360              if (!event.isDefaultPrevented()) {
47361                  if (_this.options.shortcuts) {
47362                      _this.handleKeyMap(event);
47363                  }
47364                  else {
47365                      _this.preventDefaultEditableShortCuts(event);
47366                  }
47367              }
47368              if (_this.isLimited(1, event)) {
47369                  return false;
47370              }
47371          }).on('keyup', function (event) {
47372              _this.setLastRange();
47373              _this.context.triggerEvent('keyup', event);
47374          }).on('focus', function (event) {
47375              _this.setLastRange();
47376              _this.context.triggerEvent('focus', event);
47377          }).on('blur', function (event) {
47378              _this.context.triggerEvent('blur', event);
47379          }).on('mousedown', function (event) {
47380              _this.context.triggerEvent('mousedown', event);
47381          }).on('mouseup', function (event) {
47382              _this.setLastRange();
47383              _this.context.triggerEvent('mouseup', event);
47384          }).on('scroll', function (event) {
47385              _this.context.triggerEvent('scroll', event);
47386          }).on('paste', function (event) {
47387              _this.setLastRange();
47388              _this.context.triggerEvent('paste', event);
47389          });
47390          this.$editable.attr('spellcheck', this.options.spellCheck);
47391          // init content before set event
47392          this.$editable.html(dom.html(this.$note) || dom.emptyPara);
47393          this.$editable.on(env.inputEventName, func.debounce(function () {
47394              _this.context.triggerEvent('change', _this.$editable.html(), _this.$editable);
47395          }, 10));
47396          this.$editor.on('focusin', function (event) {
47397              _this.context.triggerEvent('focusin', event);
47398          }).on('focusout', function (event) {
47399              _this.context.triggerEvent('focusout', event);
47400          });
47401          if (!this.options.airMode) {
47402              if (this.options.width) {
47403                  this.$editor.outerWidth(this.options.width);
47404              }
47405              if (this.options.height) {
47406                  this.$editable.outerHeight(this.options.height);
47407              }
47408              if (this.options.maxHeight) {
47409                  this.$editable.css('max-height', this.options.maxHeight);
47410              }
47411              if (this.options.minHeight) {
47412                  this.$editable.css('min-height', this.options.minHeight);
47413              }
47414          }
47415          this.history.recordUndo();
47416          this.setLastRange();
47417      };
47418      Editor.prototype.destroy = function () {
47419          this.$editable.off();
47420      };
47421      Editor.prototype.handleKeyMap = function (event) {
47422          var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc'];
47423          var keys = [];
47424          if (event.metaKey) {
47425              keys.push('CMD');
47426          }
47427          if (event.ctrlKey && !event.altKey) {
47428              keys.push('CTRL');
47429          }
47430          if (event.shiftKey) {
47431              keys.push('SHIFT');
47432          }
47433          var keyName = key.nameFromCode[event.keyCode];
47434          if (keyName) {
47435              keys.push(keyName);
47436          }
47437          var eventName = keyMap[keys.join('+')];
47438          if (eventName) {
47439              if (this.context.invoke(eventName) !== false) {
47440                  event.preventDefault();
47441              }
47442          }
47443          else if (key.isEdit(event.keyCode)) {
47444              this.afterCommand();
47445          }
47446      };
47447      Editor.prototype.preventDefaultEditableShortCuts = function (event) {
47448          // B(Bold, 66) / I(Italic, 73) / U(Underline, 85)
47449          if ((event.ctrlKey || event.metaKey) &&
47450              lists.contains([66, 73, 85], event.keyCode)) {
47451              event.preventDefault();
47452          }
47453      };
47454      Editor.prototype.isLimited = function (pad, event) {
47455          pad = pad || 0;
47456          if (typeof event !== 'undefined') {
47457              if (key.isMove(event.keyCode) ||
47458                  (event.ctrlKey || event.metaKey) ||
47459                  lists.contains([key.code.BACKSPACE, key.code.DELETE], event.keyCode)) {
47460                  return false;
47461              }
47462          }
47463          if (this.options.maxTextLength > 0) {
47464              if ((this.$editable.text().length + pad) >= this.options.maxTextLength) {
47465                  return true;
47466              }
47467          }
47468          return false;
47469      };
47470      /**
47471       * create range
47472       * @return {WrappedRange}
47473       */
47474      Editor.prototype.createRange = function () {
47475          this.focus();
47476          this.setLastRange();
47477          return this.getLastRange();
47478      };
47479      Editor.prototype.setLastRange = function () {
47480          this.lastRange = range.create(this.editable);
47481      };
47482      Editor.prototype.getLastRange = function () {
47483          if (!this.lastRange) {
47484              this.setLastRange();
47485          }
47486          return this.lastRange;
47487      };
47488      /**
47489       * saveRange
47490       *
47491       * save current range
47492       *
47493       * @param {Boolean} [thenCollapse=false]
47494       */
47495      Editor.prototype.saveRange = function (thenCollapse) {
47496          if (thenCollapse) {
47497              this.getLastRange().collapse().select();
47498          }
47499      };
47500      /**
47501       * restoreRange
47502       *
47503       * restore lately range
47504       */
47505      Editor.prototype.restoreRange = function () {
47506          if (this.lastRange) {
47507              this.lastRange.select();
47508              this.focus();
47509          }
47510      };
47511      Editor.prototype.saveTarget = function (node) {
47512          this.$editable.data('target', node);
47513      };
47514      Editor.prototype.clearTarget = function () {
47515          this.$editable.removeData('target');
47516      };
47517      Editor.prototype.restoreTarget = function () {
47518          return this.$editable.data('target');
47519      };
47520      /**
47521       * currentStyle
47522       *
47523       * current style
47524       * @return {Object|Boolean} unfocus
47525       */
47526      Editor.prototype.currentStyle = function () {
47527          var rng = range.create();
47528          if (rng) {
47529              rng = rng.normalize();
47530          }
47531          return rng ? this.style.current(rng) : this.style.fromNode(this.$editable);
47532      };
47533      /**
47534       * style from node
47535       *
47536       * @param {jQuery} $node
47537       * @return {Object}
47538       */
47539      Editor.prototype.styleFromNode = function ($node) {
47540          return this.style.fromNode($node);
47541      };
47542      /**
47543       * undo
47544       */
47545      Editor.prototype.undo = function () {
47546          this.context.triggerEvent('before.command', this.$editable.html());
47547          this.history.undo();
47548          this.context.triggerEvent('change', this.$editable.html(), this.$editable);
47549      };
47550      /*
47551      * commit
47552      */
47553      Editor.prototype.commit = function () {
47554          this.context.triggerEvent('before.command', this.$editable.html());
47555          this.history.commit();
47556          this.context.triggerEvent('change', this.$editable.html(), this.$editable);
47557      };
47558      /**
47559       * redo
47560       */
47561      Editor.prototype.redo = function () {
47562          this.context.triggerEvent('before.command', this.$editable.html());
47563          this.history.redo();
47564          this.context.triggerEvent('change', this.$editable.html(), this.$editable);
47565      };
47566      /**
47567       * before command
47568       */
47569      Editor.prototype.beforeCommand = function () {
47570          this.context.triggerEvent('before.command', this.$editable.html());
47571          // keep focus on editable before command execution
47572          this.focus();
47573      };
47574      /**
47575       * after command
47576       * @param {Boolean} isPreventTrigger
47577       */
47578      Editor.prototype.afterCommand = function (isPreventTrigger) {
47579          this.normalizeContent();
47580          this.history.recordUndo();
47581          if (!isPreventTrigger) {
47582              this.context.triggerEvent('change', this.$editable.html(), this.$editable);
47583          }
47584      };
47585      /**
47586       * handle tab key
47587       */
47588      Editor.prototype.tab = function () {
47589          var rng = this.getLastRange();
47590          if (rng.isCollapsed() && rng.isOnCell()) {
47591              this.table.tab(rng);
47592          }
47593          else {
47594              if (this.options.tabSize === 0) {
47595                  return false;
vendor: 6,446 bytes, lines 47596-47772
47596              }
47597              if (!this.isLimited(this.options.tabSize)) {
47598                  this.beforeCommand();
47599                  this.typing.insertTab(rng, this.options.tabSize);
47600                  this.afterCommand();
47601              }
47602          }
47603      };
47604      /**
47605       * handle shift+tab key
47606       */
47607      Editor.prototype.untab = function () {
47608          var rng = this.getLastRange();
47609          if (rng.isCollapsed() && rng.isOnCell()) {
47610              this.table.tab(rng, true);
47611          }
47612          else {
47613              if (this.options.tabSize === 0) {
47614                  return false;
47615              }
47616          }
47617      };
47618      /**
47619       * run given function between beforeCommand and afterCommand
47620       */
47621      Editor.prototype.wrapCommand = function (fn) {
47622          return function () {
47623              this.beforeCommand();
47624              fn.apply(this, arguments);
47625              this.afterCommand();
47626          };
47627      };
47628      /**
47629       * insert image
47630       *
47631       * @param {String} src
47632       * @param {String|Function} param
47633       * @return {Promise}
47634       */
47635      Editor.prototype.insertImage = function (src, param) {
47636          var _this = this;
47637          return createImage(src, param).then(function ($image) {
47638              _this.beforeCommand();
47639              if (typeof param === 'function') {
47640                  param($image);
47641              }
47642              else {
47643                  if (typeof param === 'string') {
47644                      $image.attr('data-filename', param);
47645                  }
47646                  $image.css('width', Math.min(_this.$editable.width(), $image.width()));
47647              }
47648              $image.show();
47649              range.create(_this.editable).insertNode($image[0]);
47650              range.createFromNodeAfter($image[0]).select();
47651              _this.setLastRange();
47652              _this.afterCommand();
47653          }).fail(function (e) {
47654              _this.context.triggerEvent('image.upload.error', e);
47655          });
47656      };
47657      /**
47658       * insertImages
47659       * @param {File[]} files
47660       */
47661      Editor.prototype.insertImagesAsDataURL = function (files) {
47662          var _this = this;
47663          $$1.each(files, function (idx, file) {
47664              var filename = file.name;
47665              if (_this.options.maximumImageFileSize && _this.options.maximumImageFileSize < file.size) {
47666                  _this.context.triggerEvent('image.upload.error', _this.lang.image.maximumFileSizeError);
47667              }
47668              else {
47669                  readFileAsDataURL(file).then(function (dataURL) {
47670                      return _this.insertImage(dataURL, filename);
47671                  }).fail(function () {
47672                      _this.context.triggerEvent('image.upload.error');
47673                  });
47674              }
47675          });
47676      };
47677      /**
47678       * insertImagesOrCallback
47679       * @param {File[]} files
47680       */
47681      Editor.prototype.insertImagesOrCallback = function (files) {
47682          var callbacks = this.options.callbacks;
47683          // If onImageUpload set,
47684          if (callbacks.onImageUpload) {
47685              this.context.triggerEvent('image.upload', files);
47686              // else insert Image as dataURL
47687          }
47688          else {
47689              this.insertImagesAsDataURL(files);
47690          }
47691      };
47692      /**
47693       * return selected plain text
47694       * @return {String} text
47695       */
47696      Editor.prototype.getSelectedText = function () {
47697          var rng = this.getLastRange();
47698          // if range on anchor, expand range with anchor
47699          if (rng.isOnAnchor()) {
47700              rng = range.createFromNode(dom.ancestor(rng.sc, dom.isAnchor));
47701          }
47702          return rng.toString();
47703      };
47704      Editor.prototype.onFormatBlock = function (tagName, $target) {
47705          // [workaround] for MSIE, IE need `<`
47706          document.execCommand('FormatBlock', false, env.isMSIE ? '<' + tagName + '>' : tagName);
47707          // support custom class
47708          if ($target && $target.length) {
47709              // find the exact element has given tagName
47710              if ($target[0].tagName.toUpperCase() !== tagName.toUpperCase()) {
47711                  $target = $target.find(tagName);
47712              }
47713              if ($target && $target.length) {
47714                  var className = $target[0].className || '';
47715                  if (className) {
47716                      var currentRange = this.createRange();
47717                      var $parent = $$1([currentRange.sc, currentRange.ec]).closest(tagName);
47718                      $parent.addClass(className);
47719                  }
47720              }
47721          }
47722      };
47723      Editor.prototype.formatPara = function () {
47724          this.formatBlock('P');
47725      };
47726      Editor.prototype.fontStyling = function (target, value) {
47727          var rng = this.getLastRange();
47728          if (rng) {
47729              var spans = this.style.styleNodes(rng);
47730              $$1(spans).css(target, value);
47731              // [workaround] added styled bogus span for style
47732              //  - also bogus character needed for cursor position
47733              if (rng.isCollapsed()) {
47734                  var firstSpan = lists.head(spans);
47735                  if (firstSpan && !dom.nodeLength(firstSpan)) {
47736                      firstSpan.innerHTML = dom.ZERO_WIDTH_NBSP_CHAR;
47737                      range.createFromNodeAfter(firstSpan.firstChild).select();
47738                      this.setLastRange();
47739                      this.$editable.data(KEY_BOGUS, firstSpan);
47740                  }
47741              }
47742          }
47743      };
47744      /**
47745       * unlink
47746       *
47747       * @type command
47748       */
47749      Editor.prototype.unlink = function () {
47750          var rng = this.getLastRange();
47751          if (rng.isOnAnchor()) {
47752              var anchor = dom.ancestor(rng.sc, dom.isAnchor);
47753              rng = range.createFromNode(anchor);
47754              rng.select();
47755              this.setLastRange();
47756              this.beforeCommand();
47757              document.execCommand('unlink');
47758              this.afterCommand();
47759          }
47760      };
47761      /**
47762       * returns link info
47763       *
47764       * @return {Object}
47765       * @return {WrappedRange} return.range
47766       * @return {String} return.text
47767       * @return {Boolean} [return.isNewWindow=true]
47768       * @return {String} [return.url=""]
47769       */
47770      Editor.prototype.getLinkInfo = function () {
47771          var rng = this.getLastRange().expand(dom.isAnchor);
47772          // Get the first anchor on range(for edit).
47773          var $anchor = $$1(lists.head(rng.nodes(dom.isAnchor)));
47774          var linkInfo = {
47775              range: rng,
47776              text: rng.toString(),
47777              url: $anchor.length ? $anchor.attr('href') : ''
47778          };
47779          // When anchor exists,
47780          if ($anchor.length) {
47781              // Set isNewWindow by checking its target.
47782              linkInfo.isNewWindow = $anchor.attr('target') === '_blank';
47783          }
47784          return linkInfo;
47785      };
47786      Editor.prototype.addRow = function (position) {
47787          var rng = this.getLastRange(this.$editable);
47788          if (rng.isCollapsed() && rng.isOnCell()) {
47789              this.beforeCommand();
47790              this.table.addRow(rng, position);
47791              this.afterCommand();
47792          }
47793      };
47794      Editor.prototype.addCol = function (position) {
47795          var rng = this.getLastRange(this.$editable);
47796          if (rng.isCollapsed() && rng.isOnCell()) {
47797              this.beforeCommand();
47798              this.table.addCol(rng, position);
47799              this.afterCommand();
47800          }
47801      };
47802      Editor.prototype.deleteRow = function () {
47803          var rng = this.getLastRange(this.$editable);
47804          if (rng.isCollapsed() && rng.isOnCell()) {
47805              this.beforeCommand();
47806              this.table.deleteRow(rng);
47807              this.afterCommand();
47808          }
47809      };
47810      Editor.prototype.deleteCol = function () {
47811          var rng = this.getLastRange(this.$editable);
47812          if (rng.isCollapsed() && rng.isOnCell()) {
47813              this.beforeCommand();
47814              this.table.deleteCol(rng);
47815              this.afterCommand();
47816          }
47817      };
47818      Editor.prototype.deleteTable = function () {
47819          var rng = this.getLastRange(this.$editable);
47820          if (rng.isCollapsed() && rng.isOnCell()) {
47821              this.beforeCommand();
47822              this.table.deleteTable(rng);
47823              this.afterCommand();
47824          }
47825      };
47826      /**
47827       * @param {Position} pos
47828       * @param {jQuery} $target - target element
47829       * @param {Boolean} [bKeepRatio] - keep ratio
47830       */
47831      Editor.prototype.resizeTo = function (pos, $target, bKeepRatio) {
47832          var imageSize;
47833          if (bKeepRatio) {
47834              var newRatio = pos.y / pos.x;
47835              var ratio = $target.data('ratio');
47836              imageSize = {
47837                  width: ratio > newRatio ? pos.x : pos.y / ratio,
47838                  height: ratio > newRatio ? pos.x * ratio : pos.y
47839              };
47840          }
47841          else {
47842              imageSize = {
47843                  width: pos.x,
47844                  height: pos.y
47845              };
47846          }
47847          $target.css(imageSize);
47848      };
47849      /**
47850       * returns whether editable area has focus or not.
47851       */
47852      Editor.prototype.hasFocus = function () {
47853          return this.$editable.is(':focus');
47854      };
47855      /**
47856       * set focus
47857       */
47858      Editor.prototype.focus = function () {
47859          // [workaround] Screen will move when page is scolled in IE.
47860          //  - do focus when not focused
47861          if (!this.hasFocus()) {
47862              this.$editable.focus();
47863          }
47864      };
47865      /**
47866       * returns whether contents is empty or not.
47867       * @return {Boolean}
47868       */
47869      Editor.prototype.isEmpty = function () {
47870          return dom.isEmpty(this.$editable[0]) || dom.emptyPara === this.$editable.html();
47871      };
47872      /**
47873       * Removes all contents and restores the editable instance to an _emptyPara_.
47874       */
47875      Editor.prototype.empty = function () {
47876          this.context.invoke('code', dom.emptyPara);
47877      };
47878      /**
47879       * normalize content
47880       */
47881      Editor.prototype.normalizeContent = function () {
47882          this.$editable[0].normalize();
47883      };
47884      return Editor;
47885  }());
47886
47887  var Clipboard = /** @class */ (function () {
47888      function Clipboard(context) {
47889          this.context = context;
47890          this.$editable = context.layoutInfo.editable;
47891      }
47892      Clipboard.prototype.initialize = function () {
47893          this.$editable.on('paste', this.pasteByEvent.bind(this));
47894      };
47895      /**
47896       * paste by clipboard event
47897       *
47898       * @param {Event} event
47899       */
47900      Clipboard.prototype.pasteByEvent = function (event) {
47901          var clipboardData = event.originalEvent.clipboardData;
47902          if (clipboardData && clipboardData.items && clipboardData.items.length) {
47903              // paste img file
47904              var item = clipboardData.items.length > 1 ? clipboardData.items[1] : lists.head(clipboardData.items);
47905              if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
47906                  this.context.invoke('editor.insertImagesOrCallback', [item.getAsFile()]);
47907              }
47908              this.context.invoke('editor.afterCommand');
47909          }
47910      };
47911      return Clipboard;
47912  }());
47913
47914  var Dropzone = /** @class */ (function () {
47915      function Dropzone(context) {
47916          this.context = context;
47917          this.$eventListener = $$1(document);
47918          this.$editor = context.layoutInfo.editor;
47919          this.$editable = context.layoutInfo.editable;
47920          this.options = context.options;
47921          this.lang = this.options.langInfo;
47922          this.documentEventHandlers = {};
47923          this.$dropzone = $$1([
47924              '<div class="note-dropzone">',
47925              '  <div class="note-dropzone-message"/>',
47926              '</div>',
47927          ].join('')).prependTo(this.$editor);
47928      }
47929      /**
47930       * attach Drag and Drop Events
47931       */
47932      Dropzone.prototype.initialize = function () {
47933          if (this.options.disableDragAndDrop) {
47934              // prevent default drop event
47935              this.documentEventHandlers.onDrop = function (e) {
47936                  e.preventDefault();
47937              };
47938              // do not consider outside of dropzone
47939              this.$eventListener = this.$dropzone;
47940              this.$eventListener.on('drop', this.documentEventHandlers.onDrop);
47941          }
47942          else {
47943              this.attachDragAndDropEvent();
47944          }
47945      };
47946      /**
47947       * attach Drag and Drop Events
47948       */
47949      Dropzone.prototype.attachDragAndDropEvent = function () {
47950          var _this = this;
47951          var collection = $$1();
47952          var $dropzoneMessage = this.$dropzone.find('.note-dropzone-message');
47953          this.documentEventHandlers.onDragenter = function (e) {
47954              var isCodeview = _this.context.invoke('codeview.isActivated');
47955              var hasEditorSize = _this.$editor.width() > 0 && _this.$editor.height() > 0;
47956              if (!isCodeview && !collection.length && hasEditorSize) {
47957                  _this.$editor.addClass('dragover');
47958                  _this.$dropzone.width(_this.$editor.width());
47959                  _this.$dropzone.height(_this.$editor.height());
47960                  $dropzoneMessage.text(_this.lang.image.dragImageHere);
47961              }
47962              collection = collection.add(e.target);
47963          };
47964          this.documentEventHandlers.onDragleave = function (e) {
47965              collection = collection.not(e.target);
47966              if (!collection.length) {
47967                  _this.$editor.removeClass('dragover');
47968              }
47969          };
47970          this.documentEventHandlers.onDrop = function () {
47971              collection = $$1();
47972              _this.$editor.removeClass('dragover');
47973          };
47974          // show dropzone on dragenter when dragging a object to document
47975          // -but only if the editor is visible, i.e. has a positive width and height
47976          this.$eventListener.on('dragenter', this.documentEventHandlers.onDragenter)
47977              .on('dragleave', this.documentEventHandlers.onDragleave)
47978              .on('drop', this.documentEventHandlers.onDrop);
47979          // change dropzone's message on hover.
47980          this.$dropzone.on('dragenter', function () {
47981              _this.$dropzone.addClass('hover');
47982              $dropzoneMessage.text(_this.lang.image.dropImage);
47983          }).on('dragleave', function () {
47984              _this.$dropzone.removeClass('hover');
47985              $dropzoneMessage.text(_this.lang.image.dragImageHere);
47986          });
47987          // attach dropImage
47988          this.$dropzone.on('drop', function (event) {
47989              var dataTransfer = event.originalEvent.dataTransfer;
47990              // stop the browser from opening the dropped content
47991              event.preventDefault();
47992              if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
47993                  _this.$editable.focus();
47994                  _this.context.invoke('editor.insertImagesOrCallback', dataTransfer.files);
47995              }
47996              else {
47997                  $$1.each(dataTransfer.types, function (idx, type) {
47998                      var content = dataTransfer.getData(type);
47999                      if (type.toLowerCase().indexOf('text') > -1) {
48000                          _this.context.invoke('editor.pasteHTML', content);
48001                      }
48002                      else {
48003                          $$1(content).each(function (idx, item) {
48004                              _this.context.invoke('editor.insertNode', item);
48005                          });
48006                      }
48007                  });
48008              }
48009          }).on('dragover', false); // prevent default dragover event
48010      };
48011      Dropzone.prototype.destroy = function () {
48012          var _this = this;
48013          Object.keys(this.documentEventHandlers).forEach(function (key) {
48014              _this.$eventListener.off(key.substr(2).toLowerCase(), _this.documentEventHandlers[key]);
48015          });
48016          this.documentEventHandlers = {};
48017      };
48018      return Dropzone;
48019  }());
48020
48021  var CodeMirror;
48022  if (env.hasCodeMirror) {
48023      CodeMirror = window.CodeMirror;
48024  }
48025  /**
48026   * @class Codeview
48027   */
48028  var CodeView = /** @class */ (function () {
48029      function CodeView(context) {
48030          this.context = context;
48031          this.$editor = context.layoutInfo.editor;
48032          this.$editable = context.layoutInfo.editable;
48033          this.$codable = context.layoutInfo.codable;
48034          this.options = context.options;
48035      }
48036      CodeView.prototype.sync = function () {
48037          var isCodeview = this.isActivated();
48038          if (isCodeview && env.hasCodeMirror) {
48039              this.$codable.data('cmEditor').save();
48040          }
48041      };
48042      /**
48043       * @return {Boolean}
48044       */
48045      CodeView.prototype.isActivated = function () {
48046          return this.$editor.hasClass('codeview');
48047      };
48048      /**
48049       * toggle codeview
48050       */
48051      CodeView.prototype.toggle = function () {
48052          if (this.isActivated()) {
48053              this.deactivate();
48054          }
48055          else {
48056              this.activate();
48057          }
48058          this.context.triggerEvent('codeview.toggled');
48059      };
48060      /**
48061       * purify input value
48062       * @param value
48063       * @returns {*}
48064       */
48065      CodeView.prototype.purify = function (value) {
48066          if (this.options.codeviewFilter) {
48067              // filter code view regex
48068              value = value.replace(this.options.codeviewFilterRegex, '');
48069              // allow specific iframe tag
48070              if (this.options.codeviewIframeFilter) {
48071                  var whitelist_1 = this.options.codeviewIframeWhitelistSrc.concat(this.options.codeviewIframeWhitelistSrcBase);
48072                  value = value.replace(/(<iframe.*?>.*?(?:<\/iframe>)?)/gi, function (tag) {
48073                      // remove if src attribute is duplicated
48074                      if (/<.+src(?==?('|"|\s)?)[\s\S]+src(?=('|"|\s)?)[^>]*?>/i.test(tag)) {
48075                          return '';
48076                      }
48077                      for (var _i = 0, whitelist_2 = whitelist_1; _i < whitelist_2.length; _i++) {
48078                          var src = whitelist_2[_i];
48079                          // pass if src is trusted
48080                          if ((new RegExp('src="(https?:)?\/\/' + src.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '\/(.+)"')).test(tag)) {
48081                              return tag;
48082                          }
48083                      }
48084                      return '';
48085                  });
48086              }
48087          }
48088          return value;
48089      };
48090      /**
48091       * activate code view
48092       */
48093      CodeView.prototype.activate = function () {
48094          var _this = this;
48095          this.$codable.val(dom.html(this.$editable, this.options.prettifyHtml));
48096          this.$codable.height(this.$editable.height());
48097          this.context.invoke('toolbar.updateCodeview', true);
48098          this.$editor.addClass('codeview');
48099          this.$codable.focus();
48100          // activate CodeMirror as codable
48101          if (env.hasCodeMirror) {
48102              var cmEditor_1 = CodeMirror.fromTextArea(this.$codable[0], this.options.codemirror);
48103              // CodeMirror TernServer
48104              if (this.options.codemirror.tern) {
48105                  var server_1 = new CodeMirror.TernServer(this.options.codemirror.tern);
48106                  cmEditor_1.ternServer = server_1;
48107                  cmEditor_1.on('cursorActivity', function (cm) {
48108                      server_1.updateArgHints(cm);
48109                  });
48110              }
48111              cmEditor_1.on('blur', function (event) {
48112                  _this.context.triggerEvent('blur.codeview', cmEditor_1.getValue(), event);
48113              });
48114              cmEditor_1.on('change', function (event) {
48115                  _this.context.triggerEvent('change.codeview', cmEditor_1.getValue(), cmEditor_1);
48116              });
48117              // CodeMirror hasn't Padding.
48118              cmEditor_1.setSize(null, this.$editable.outerHeight());
48119              this.$codable.data('cmEditor', cmEditor_1);
48120          }
48121          else {
48122              this.$codable.on('blur', function (event) {
48123                  _this.context.triggerEvent('blur.codeview', _this.$codable.val(), event);
48124              });
48125              this.$codable.on('input', function (event) {
48126                  _this.context.triggerEvent('change.codeview', _this.$codable.val(), _this.$codable);
48127              });
48128          }
48129      };
48130      /**
48131       * deactivate code view
48132       */
48133      CodeView.prototype.deactivate = function () {
48134          // deactivate CodeMirror as codable
48135          if (env.hasCodeMirror) {
48136              var cmEditor = this.$codable.data('cmEditor');
48137              this.$codable.val(cmEditor.getValue());
48138              cmEditor.toTextArea();
48139          }
48140          var value = this.purify(dom.value(this.$codable, this.options.prettifyHtml) || dom.emptyPara);
48141          var isChange = this.$editable.html() !== value;
48142          this.$editable.html(value);
48143          this.$editable.height(this.options.height ? this.$codable.height() : 'auto');
48144          this.$editor.removeClass('codeview');
48145          if (isChange) {
48146              this.context.triggerEvent('change', this.$editable.html(), this.$editable);
48147          }
48148          this.$editable.focus();
48149          this.context.invoke('toolbar.updateCodeview', false);
48150      };
48151      CodeView.prototype.destroy = function () {
48152          if (this.isActivated()) {
48153              this.deactivate();
48154          }
48155      };
48156      return CodeView;
48157  }());
48158
48159  var EDITABLE_PADDING = 24;
48160  var Statusbar = /** @class */ (function () {
48161      function Statusbar(context) {
48162          this.$document = $$1(document);
48163          this.$statusbar = context.layoutInfo.statusbar;
48164          this.$editable = context.layoutInfo.editable;
48165          this.options = context.options;
48166      }
48167      Statusbar.prototype.initialize = function () {
48168          var _this = this;
48169          if (this.options.airMode || this.options.disableResizeEditor) {
48170              this.destroy();
48171              return;
48172          }
48173          this.$statusbar.on('mousedown', function (event) {
48174              event.preventDefault();
48175              event.stopPropagation();
48176              var editableTop = _this.$editable.offset().top - _this.$document.scrollTop();
48177              var onMouseMove = function (event) {
48178                  var height = event.clientY - (editableTop + EDITABLE_PADDING);
48179                  height = (_this.options.minheight > 0) ? Math.max(height, _this.options.minheight) : height;
48180                  height = (_this.options.maxHeight > 0) ? Math.min(height, _this.options.maxHeight) : height;
48181                  _this.$editable.height(height);
48182              };
48183              _this.$document.on('mousemove', onMouseMove).one('mouseup', function () {
48184                  _this.$document.off('mousemove', onMouseMove);
48185              });
48186          });
48187
48188          this.$statusbar.on('touchstart', function (event) {
48189              event.stopPropagation();
48190              var editableTop = _this.$editable.offset().top - _this.$document.scrollTop();
48191              var onTouchMove = function (event) {
48192                  var height = event.touches[0].clientY - (editableTop + EDITABLE_PADDING);
48193                  height = (_this.options.minheight > 0) ? Math.max(height, _this.options.minheight) : height;
48194                  height = (_this.options.maxHeight > 0) ? Math.min(height, _this.options.maxHeight) : height;
48195                  _this.$editable.height(height);
48196              };
48197              _this.$document.on('touchmove', onTouchMove).one('touchend', function () {
48198                  _this.$document.off('touchmove', onTouchMove);
48199              });
48200          });
48201      };
48202      Statusbar.prototype.destroy = function () {
48203          this.$statusbar.off();
48204          this.$statusbar.addClass('locked');
48205      };
48206      return Statusbar;
48207  }());
48208
48209  var Fullscreen = /** @class */ (function () {
48210      function Fullscreen(context) {
48211          var _this = this;
48212          this.context = context;
48213          this.$editor = context.layoutInfo.editor;
48214          this.$toolbar = context.layoutInfo.toolbar;
48215          this.$editable = context.layoutInfo.editable;
48216          this.$codable = context.layoutInfo.codable;
48217          this.$window = $$1(window);
48218          this.$scrollbar = $$1('html, body');
48219          this.onResize = function () {
48220              _this.resizeTo({
48221                  h: _this.$window.height() - _this.$toolbar.outerHeight()
48222              });
48223          };
48224      }
48225      Fullscreen.prototype.resizeTo = function (size) {
48226          this.$editable.css('height', size.h);
48227          this.$codable.css('height', size.h);
48228          if (this.$codable.data('cmeditor')) {
48229              this.$codable.data('cmeditor').setsize(null, size.h);
48230          }
48231      };
48232      /**
48233       * toggle fullscreen
48234       */
48235      Fullscreen.prototype.toggle = function () {
48236          this.$editor.toggleClass('fullscreen');
48237          if (this.isFullscreen()) {
48238              this.$editable.data('orgHeight', this.$editable.css('height'));
48239              this.$editable.data('orgMaxHeight', this.$editable.css('maxHeight'));
48240              this.$editable.css('maxHeight', '');
48241              this.$window.on('resize', this.onResize).trigger('resize');
48242              this.$scrollbar.css('overflow', 'hidden');
48243          }
48244          else {
48245              this.$window.off('resize', this.onResize);
48246              this.resizeTo({ h: this.$editable.data('orgHeight') });
48247              this.$editable.css('maxHeight', this.$editable.css('orgMaxHeight'));
48248              this.$scrollbar.css('overflow', 'visible');
48249          }
48250          this.context.invoke('toolbar.updateFullscreen', this.isFullscreen());
48251      };
48252      Fullscreen.prototype.isFullscreen = function () {
48253          return this.$editor.hasClass('fullscreen');
48254      };
48255      return Fullscreen;
48256  }());
48257
48258  var Handle = /** @class */ (function () {
48259      function Handle(context) {
48260          var _this = this;
48261          this.context = context;
48262          this.$document = $$1(document);
48263          this.$editingArea = context.layoutInfo.editingArea;
48264          this.options = context.options;
48265          this.lang = this.options.langInfo;
48266          this.events = {
48267              'summernote.mousedown': function (we, e) {
48268                  if (_this.update(e.target, e)) {
48269                      e.preventDefault();
48270                  }
48271              },
48272              'summernote.keyup summernote.scroll summernote.change summernote.dialog.shown': function () {
48273                  _this.update();
48274              },
48275              'summernote.disable': function () {
48276                  _this.hide();
48277              },
48278              'summernote.codeview.toggled': function () {
48279                  _this.update();
48280              }
48281          };
48282      }
48283      Handle.prototype.initialize = function () {
48284          var _this = this;
48285          this.$handle = $$1([
48286              '<div class="note-handle">',
48287              '<div class="note-control-selection">',
48288              '<div class="note-control-selection-bg"></div>',
48289              '<div class="note-control-holder note-control-nw"></div>',
48290              '<div class="note-control-holder note-control-ne"></div>',
48291              '<div class="note-control-holder note-control-sw"></div>',
48292              '<div class="',
48293              (this.options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing'),
48294              ' note-control-se"></div>',
48295              (this.options.disableResizeImage ? '' : '<div class="note-control-selection-info"></div>'),
48296              '</div>',
48297              '</div>',
48298          ].join('')).prependTo(this.$editingArea);
48299          this.$handle.on('mousedown', function (event) {
48300              if (dom.isControlSizing(event.target)) {
48301                  event.preventDefault();
48302                  event.stopPropagation();
48303                  var $target_1 = _this.$handle.find('.note-control-selection').data('target');
48304                  var posStart_1 = $target_1.offset();
48305                  var scrollTop_1 = _this.$document.scrollTop();
48306                  var onMouseMove_1 = function (event) {
48307                      _this.context.invoke('editor.resizeTo', {
48308                          x: event.clientX - posStart_1.left,
48309                          y: event.clientY - (posStart_1.top - scrollTop_1)
48310                      }, $target_1, !event.shiftKey);
48311                      _this.update($target_1[0], event);
48312                  };
48313                  _this.$document
48314                      .on('mousemove', onMouseMove_1)
48315                      .one('mouseup', function (e) {
48316                      e.preventDefault();
48317                      _this.$document.off('mousemove', onMouseMove_1);
48318                      _this.context.invoke('editor.afterCommand');
48319                  });
48320                  if (!$target_1.data('ratio')) { // original ratio.
48321                      $target_1.data('ratio', $target_1.height() / $target_1.width());
48322                  }
48323              }
48324          });
48325
48326          this.$handle.on('touchstart', function (event) {
48327              if (dom.isControlSizing(event.target)) {
48328                  event.preventDefault();
48329                  event.stopPropagation();
48330
48331                  var $target = _this.$handle.find('.note-control-selection').data('target'),
48332                      posStart = $target.offset(),
48333                      scrollTop = _this.$document.scrollTop();
48334
48335                  _this.$document.on('touchmove', function (event) {
48336                      _this.context.invoke('editor.resizeTo', {
48337                          x: event.touches[0].clientX - posStart.left,
48338                          y: event.touches[0].clientY - (posStart.top - scrollTop)
48339                      }, $target, !event.shiftKey);
48340
48341                      _this.update($target[0], event);
48342                  }).one('touchend', function (e) {
48343                      e.preventDefault();
48344                      _this.$document.off('touchmove');
48345                      _this.context.invoke('editor.afterCommand');
48346                  });
48347
48348                  if (!$target.data('ratio')) { // original ratio.
48349                      $target.data('ratio', $target.height() / $target.width());
48350                  }
48351              }
48352          });
48353          // Listen for scrolling on the handle overlay.
48354          this.$handle.on('wheel', function (e) {
48355              e.preventDefault();
48356              _this.update();
48357          });
48358      };
48359      Handle.prototype.destroy = function () {
48360          this.$handle.remove();
48361      };
48362      Handle.prototype.update = function (target, event) {
48363          if (this.context.isDisabled()) {
48364              return false;
48365          }
48366          var isImage = dom.isImg(target);
48367          var $selection = this.$handle.find('.note-control-selection');
48368          this.context.invoke('imagePopover.update', target, event);
48369          if (isImage) {
48370              var $image = $$1(target);
48371              var position = $image.position();
48372              var pos = {
48373                  left: position.left + parseInt($image.css('marginLeft'), 10),
48374                  top: position.top + parseInt($image.css('marginTop'), 10)
48375              };
48376              // exclude margin
48377              var imageSize = {
48378                  w: $image.outerWidth(false),
48379                  h: $image.outerHeight(false)
48380              };
48381              $selection.css({
48382                  display: 'block',
48383                  left: pos.left,
48384                  top: pos.top,
48385                  width: imageSize.w,
48386                  height: imageSize.h
48387              }).data('target', $image); // save current image element.
48388              var origImageObj = new Image();
48389              origImageObj.src = $image.attr('src');
48390              var sizingText = imageSize.w + 'x' + imageSize.h + ' (' + this.lang.image.original + ': ' + origImageObj.width + 'x' + origImageObj.height + ')';
48391              $selection.find('.note-control-selection-info').text(sizingText);
48392              this.context.invoke('editor.saveTarget', target);
48393          }
48394          else {
48395              this.hide();
48396          }
48397          return isImage;
48398      };
48399      /**
48400       * hide
48401       *
48402       * @param {jQuery} $handle
48403       */
48404      Handle.prototype.hide = function () {
48405          this.context.invoke('editor.clearTarget');
48406          this.$handle.children().hide();
48407      };
48408      return Handle;
48409  }());
48410
48411  var defaultScheme = 'http://';
48412  var linkPattern = /^([A-Za-z][A-Za-z0-9+-.]*\:[\/]{2}|mailto:[A-Z0-9._%+-]+@)?(www\.)?(.+)$/i;
48413  var AutoLink = /** @class */ (function () {
48414      function AutoLink(context) {
48415          var _this = this;
48416          this.context = context;
48417          this.events = {
48418              'summernote.keyup': function (we, e) {
48419                  if (!e.isDefaultPrevented()) {
48420                      _this.handleKeyup(e);
48421                  }
48422              },
48423              'summernote.keydown': function (we, e) {
48424                  _this.handleKeydown(e);
48425              }
48426          };
48427      }
48428      AutoLink.prototype.initialize = function () {
48429          this.lastWordRange = null;
48430      };
48431      AutoLink.prototype.destroy = function () {
48432          this.lastWordRange = null;
48433      };
48434      AutoLink.prototype.replace = function () {
48435          if (!this.lastWordRange) {
48436              return;
48437          }
48438          var keyword = this.lastWordRange.toString();
48439          var match = keyword.match(linkPattern);
48440          if (match && (match[1] || match[2])) {
48441              var link = match[1] ? keyword : defaultScheme + keyword;
48442              var node = $$1('<a />').html(keyword).attr('href', link)[0];
48443              if (this.context.options.linkTargetBlank) {
48444                  $$1(node).attr('target', '_blank');
48445              }
48446              this.lastWordRange.insertNode(node);
48447              this.lastWordRange = null;
48448              this.context.invoke('editor.focus');
48449          }
48450      };
48451      AutoLink.prototype.handleKeydown = function (e) {
48452          if (lists.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
48453              var wordRange = this.context.invoke('editor.createRange').getWordRange();
48454              this.lastWordRange = wordRange;
48455          }
48456      };
48457      AutoLink.prototype.handleKeyup = function (e) {
48458          if (lists.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) {
48459              this.replace();
48460          }
48461      };
48462      return AutoLink;
48463  }());
48464
48465  /**
48466   * textarea auto sync.
48467   */
48468  var AutoSync = /** @class */ (function () {
48469      function AutoSync(context) {
48470          var _this = this;
48471          this.$note = context.layoutInfo.note;
48472          this.events = {
48473              'summernote.change': function () {
48474                  _this.$note.val(context.invoke('code'));
48475              }
48476          };
48477      }
48478      AutoSync.prototype.shouldInitialize = function () {
48479          return dom.isTextarea(this.$note[0]);
48480      };
48481      return AutoSync;
48482  }());
48483
48484  var AutoReplace = /** @class */ (function () {
48485      function AutoReplace(context) {
48486          var _this = this;
48487          this.context = context;
48488          this.options = context.options.replace || {};
48489          this.keys = [key.code.ENTER, key.code.SPACE, key.code.PERIOD, key.code.COMMA, key.code.SEMICOLON, key.code.SLASH];
48490          this.previousKeydownCode = null;
48491          this.events = {
48492              'summernote.keyup': function (we, e) {
48493                  if (!e.isDefaultPrevented()) {
48494                      _this.handleKeyup(e);
48495                  }
48496              },
48497              'summernote.keydown': function (we, e) {
48498                  _this.handleKeydown(e);
48499              }
48500          };
48501      }
48502      AutoReplace.prototype.shouldInitialize = function () {
48503          return !!this.options.match;
48504      };
48505      AutoReplace.prototype.initialize = function () {
48506          this.lastWord = null;
48507      };
48508      AutoReplace.prototype.destroy = function () {
48509          this.lastWord = null;
48510      };
48511      AutoReplace.prototype.replace = function () {
48512          if (!this.lastWord) {
48513              return;
48514          }
48515          var self = this;
48516          var keyword = this.lastWord.toString();
48517          this.options.match(keyword, function (match) {
48518              if (match) {
48519                  var node = '';
48520                  if (typeof match === 'string') {
48521                      node = dom.createText(match);
48522                  }
48523                  else if (match instanceof jQuery) {
48524                      node = match[0];
48525                  }
48526                  else if (match instanceof Node) {
48527                      node = match;
48528                  }
48529                  if (!node)
48530                      return;
48531                  self.lastWord.insertNode(node);
48532                  self.lastWord = null;
48533                  self.context.invoke('editor.focus');
48534              }
48535          });
48536      };
48537      AutoReplace.prototype.handleKeydown = function (e) {
48538          // this forces it to remember the last whole word, even if multiple termination keys are pressed
48539          // before the previous key is let go.
48540          if (this.previousKeydownCode && lists.contains(this.keys, this.previousKeydownCode)) {
48541              this.previousKeydownCode = e.keyCode;
48542              return;
48543          }
48544          if (lists.contains(this.keys, e.keyCode)) {
48545              var wordRange = this.context.invoke('editor.createRange').getWordRange();
48546              this.lastWord = wordRange;
48547          }
48548          this.previousKeydownCode = e.keyCode;
48549      };
48550      AutoReplace.prototype.handleKeyup = function (e) {
48551          if (lists.contains(this.keys, e.keyCode)) {
48552              this.replace();
48553          }
48554      };
48555      return AutoReplace;
48556  }());
48557
48558  var Placeholder = /** @class */ (function () {
48559      function Placeholder(context) {
48560          var _this = this;
48561          this.context = context;
48562          this.$editingArea = context.layoutInfo.editingArea;
48563          this.options = context.options;
48564          this.events = {
48565              'summernote.init summernote.change': function () {
48566                  _this.update();
48567              },
48568              'summernote.codeview.toggled': function () {
48569                  _this.update();
48570              }
48571          };
48572      }
48573      Placeholder.prototype.shouldInitialize = function () {
48574          return !!this.options.placeholder;
48575      };
48576      Placeholder.prototype.initialize = function () {
48577          var _this = this;
48578          this.$placeholder = $$1('<div class="note-placeholder">');
48579          this.$placeholder.on('click', function () {
vendor: 11,434 bytes, lines 48580-48786
48580              _this.context.invoke('focus');
48581          }).html(this.options.placeholder).prependTo(this.$editingArea);
48582          this.update();
48583      };
48584      Placeholder.prototype.destroy = function () {
48585          this.$placeholder.remove();
48586      };
48587      Placeholder.prototype.update = function () {
48588          var isShow = !this.context.invoke('codeview.isActivated') && this.context.invoke('editor.isEmpty');
48589          this.$placeholder.toggle(isShow);
48590      };
48591      return Placeholder;
48592  }());
48593
48594  var Buttons = /** @class */ (function () {
48595      function Buttons(context) {
48596          this.ui = $$1.summernote.ui;
48597          this.context = context;
48598          this.$toolbar = context.layoutInfo.toolbar;
48599          this.options = context.options;
48600          this.lang = this.options.langInfo;
48601          this.invertedKeyMap = func.invertObject(this.options.keyMap[env.isMac ? 'mac' : 'pc']);
48602      }
48603      Buttons.prototype.representShortcut = function (editorMethod) {
48604          var shortcut = this.invertedKeyMap[editorMethod];
48605          if (!this.options.shortcuts || !shortcut) {
48606              return '';
48607          }
48608          if (env.isMac) {
48609              shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧');
48610          }
48611          shortcut = shortcut.replace('BACKSLASH', '\\')
48612              .replace('SLASH', '/')
48613              .replace('LEFTBRACKET', '[')
48614              .replace('RIGHTBRACKET', ']');
48615          return ' (' + shortcut + ')';
48616      };
48617      Buttons.prototype.button = function (o) {
48618          if (!this.options.tooltip && o.tooltip) {
48619              delete o.tooltip;
48620          }
48621          o.container = this.options.container;
48622          return this.ui.button(o);
48623      };
48624      Buttons.prototype.initialize = function () {
48625          this.addToolbarButtons();
48626          this.addImagePopoverButtons();
48627          this.addLinkPopoverButtons();
48628          this.addTablePopoverButtons();
48629          this.fontInstalledMap = {};
48630      };
48631      Buttons.prototype.destroy = function () {
48632          delete this.fontInstalledMap;
48633      };
48634      Buttons.prototype.isFontInstalled = function (name) {
48635          if (!this.fontInstalledMap.hasOwnProperty(name)) {
48636              this.fontInstalledMap[name] = env.isFontInstalled(name) ||
48637                  lists.contains(this.options.fontNamesIgnoreCheck, name);
48638          }
48639          return this.fontInstalledMap[name];
48640      };
48641      Buttons.prototype.isFontDeservedToAdd = function (name) {
48642          var genericFamilies = ['sans-serif', 'serif', 'monospace', 'cursive', 'fantasy'];
48643          name = name.toLowerCase();
48644          return (name !== '' && this.isFontInstalled(name) && genericFamilies.indexOf(name) === -1);
48645      };
48646      Buttons.prototype.colorPalette = function (className, tooltip, backColor, foreColor) {
48647          var _this = this;
48648          return this.ui.buttonGroup({
48649              className: 'note-color ' + className,
48650              children: [
48651                  this.button({
48652                      className: 'note-current-color-button',
48653                      contents: this.ui.icon(this.options.icons.font + ' note-recent-color'),
48654                      tooltip: tooltip,
48655                      click: function (e) {
48656                          var $button = $$1(e.currentTarget);
48657                          if (backColor && foreColor) {
48658                              _this.context.invoke('editor.color', {
48659                                  backColor: $button.attr('data-backColor'),
48660                                  foreColor: $button.attr('data-foreColor')
48661                              });
48662                          }
48663                          else if (backColor) {
48664                              _this.context.invoke('editor.color', {
48665                                  backColor: $button.attr('data-backColor')
48666                              });
48667                          }
48668                          else if (foreColor) {
48669                              _this.context.invoke('editor.color', {
48670                                  foreColor: $button.attr('data-foreColor')
48671                              });
48672                          }
48673                      },
48674                      callback: function ($button) {
48675                          var $recentColor = $button.find('.note-recent-color');
48676                          if (backColor) {
48677                              $recentColor.css('background-color', _this.options.colorButton.backColor);
48678                              $button.attr('data-backColor', _this.options.colorButton.backColor);
48679                          }
48680                          if (foreColor) {
48681                              $recentColor.css('color', _this.options.colorButton.foreColor);
48682                              $button.attr('data-foreColor', _this.options.colorButton.foreColor);
48683                          }
48684                          else {
48685                              $recentColor.css('color', 'transparent');
48686                          }
48687                      }
48688                  }),
48689                  this.button({
48690                      className: 'dropdown-toggle',
48691                      contents: this.ui.dropdownButtonContents('', this.options),
48692                      tooltip: this.lang.color.more,
48693                      data: {
48694                          toggle: 'dropdown'
48695                      }
48696                  }),
48697                  this.ui.dropdown({
48698                      items: (backColor ? [
48699                          '<div class="note-palette">',
48700                          '  <div class="note-palette-title">' + this.lang.color.background + '</div>',
48701                          '  <div>',
48702                          '    <button type="button" class="note-color-reset btn btn-light" data-event="backColor" data-value="inherit">',
48703                          this.lang.color.transparent,
48704                          '    </button>',
48705                          '  </div>',
48706                          '  <div class="note-holder" data-event="backColor"/>',
48707                          '  <div>',
48708                          '    <button type="button" class="note-color-select btn" data-event="openPalette" data-value="backColorPicker">',
48709                          this.lang.color.cpSelect,
48710                          '    </button>',
48711                          '    <input type="color" id="backColorPicker" class="note-btn note-color-select-btn" value="' + this.options.colorButton.backColor + '" data-event="backColorPalette">',
48712                          '  </div>',
48713                          '  <div class="note-holder-custom" id="backColorPalette" data-event="backColor"/>',
48714                          '</div>',
48715                      ].join('') : '') +
48716                          (foreColor ? [
48717                              '<div class="note-palette">',
48718                              '  <div class="note-palette-title">' + this.lang.color.foreground + '</div>',
48719                              '  <div>',
48720                              '    <button type="button" class="note-color-reset btn btn-light" data-event="removeFormat" data-value="foreColor">',
48721                              this.lang.color.resetToDefault,
48722                              '    </button>',
48723                              '  </div>',
48724                              '  <div class="note-holder" data-event="foreColor"/>',
48725                              '  <div>',
48726                              '    <button type="button" class="note-color-select btn" data-event="openPalette" data-value="foreColorPicker">',
48727                              this.lang.color.cpSelect,
48728                              '    </button>',
48729                              '    <input type="color" id="foreColorPicker" class="note-btn note-color-select-btn" value="' + this.options.colorButton.foreColor + '" data-event="foreColorPalette">',
48730                              '  <div class="note-holder-custom" id="foreColorPalette" data-event="foreColor"/>',
48731                              '</div>',
48732                          ].join('') : ''),
48733                      callback: function ($dropdown) {
48734                          $dropdown.find('.note-holder').each(function (idx, item) {
48735                              var $holder = $$1(item);
48736                              $holder.append(_this.ui.palette({
48737                                  colors: _this.options.colors,
48738                                  colorsName: _this.options.colorsName,
48739                                  eventName: $holder.data('event'),
48740                                  container: _this.options.container,
48741                                  tooltip: _this.options.tooltip
48742                              }).render());
48743                          });
48744                          /* TODO: do we have to record recent custom colors within cookies? */
48745                          var customColors = [
48746                              ['#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF'],
48747                          ];
48748                          $dropdown.find('.note-holder-custom').each(function (idx, item) {
48749                              var $holder = $$1(item);
48750                              $holder.append(_this.ui.palette({
48751                                  colors: customColors,
48752                                  colorsName: customColors,
48753                                  eventName: $holder.data('event'),
48754                                  container: _this.options.container,
48755                                  tooltip: _this.options.tooltip
48756                              }).render());
48757                          });
48758                          $dropdown.find('input[type=color]').each(function (idx, item) {
48759                              $$1(item).change(function () {
48760                                  var $chip = $dropdown.find('#' + $$1(this).data('event')).find('.note-color-btn').first();
48761                                  var color = this.value.toUpperCase();
48762                                  $chip.css('background-color', color)
48763                                      .attr('aria-label', color)
48764                                      .attr('data-value', color)
48765                                      .attr('data-original-title', color);
48766                                  $chip.click();
48767                              });
48768                          });
48769                      },
48770                      click: function (event) {
48771                          event.stopPropagation();
48772                          var $parent = $$1('.' + className);
48773                          var $button = $$1(event.target);
48774                          var eventName = $button.data('event');
48775                          var value = $button.attr('data-value');
48776                          if (eventName === 'openPalette') {
48777                              var $picker = $parent.find('#' + value);
48778                              var $palette = $$1($parent.find('#' + $picker.data('event')).find('.note-color-row')[0]);
48779                              // Shift palette chips
48780                              var $chip = $palette.find('.note-color-btn').last().detach();
48781                              // Set chip attributes
48782                              var color = $picker.val();
48783                              $chip.css('background-color', color)
48784                                  .attr('aria-label', color)
48785                                  .attr('data-value', color)
48786                                  .attr('data-original-title', color);
48787                              $palette.prepend($chip);
48788                              $picker.click();
48789                          }
48790                          else if (lists.contains(['backColor', 'foreColor'], eventName)) {
48791                              var key = eventName === 'backColor' ? 'background-color' : 'color';
48792                              var $color = $button.closest('.note-color').find('.note-recent-color');
48793                              var $currentButton = $button.closest('.note-color').find('.note-current-color-button');
48794                              $color.css(key, value);
48795                              $currentButton.attr('data-' + eventName, value);
48796                              _this.context.invoke('editor.' + eventName, value);
48797                          }
48798                      }
48799                  }),
48800              ]
48801          }).render();
48802      };
48803      Buttons.prototype.addToolbarButtons = function () {
48804          var _this = this;
48805          this.context.memo('button.style', function () {
48806              return _this.ui.buttonGroup([
48807                  _this.button({
48808                      className: 'dropdown-toggle',
48809                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.magic), _this.options),
48810                      tooltip: _this.lang.style.style,
48811                      data: {
48812                          toggle: 'dropdown'
48813                      }
48814                  }),
48815                  _this.ui.dropdown({
48816                      className: 'dropdown-style',
48817                      items: _this.options.styleTags,
48818                      title: _this.lang.style.style,
48819                      template: function (item) {
48820                          if (typeof item === 'string') {
48821                              item = { tag: item, title: (_this.lang.style.hasOwnProperty(item) ? _this.lang.style[item] : item) };
48822                          }
48823                          var tag = item.tag;
48824                          var title = item.title;
48825                          var style = item.style ? ' style="' + item.style + '" ' : '';
48826                          var className = item.className ? ' class="' + item.className + '"' : '';
48827                          return '<' + tag + style + className + '>' + title + '</' + tag + '>';
48828                      },
48829                      click: _this.context.createInvokeHandler('editor.formatBlock')
48830                  }),
48831              ]).render();
48832          });
48833          var _loop_1 = function (styleIdx, styleLen) {
48834              var item = this_1.options.styleTags[styleIdx];
48835              this_1.context.memo('button.style.' + item, function () {
48836                  return _this.button({
48837                      className: 'note-btn-style-' + item,
48838                      contents: '<div data-value="' + item + '">' + item.toUpperCase() + '</div>',
48839                      tooltip: _this.lang.style[item],
48840                      click: _this.context.createInvokeHandler('editor.formatBlock')
48841                  }).render();
48842              });
48843          };
48844          var this_1 = this;
48845          for (var styleIdx = 0, styleLen = this.options.styleTags.length; styleIdx < styleLen; styleIdx++) {
48846              _loop_1(styleIdx, styleLen);
48847          }
48848          this.context.memo('button.bold', function () {
48849              return _this.button({
48850                  className: 'note-btn-bold',
48851                  contents: _this.ui.icon(_this.options.icons.bold),
48852                  tooltip: _this.lang.font.bold + _this.representShortcut('bold'),
48853                  click: _this.context.createInvokeHandlerAndUpdateState('editor.bold')
48854              }).render();
48855          });
48856          this.context.memo('button.italic', function () {
48857              return _this.button({
48858                  className: 'note-btn-italic',
48859                  contents: _this.ui.icon(_this.options.icons.italic),
48860                  tooltip: _this.lang.font.italic + _this.representShortcut('italic'),
48861                  click: _this.context.createInvokeHandlerAndUpdateState('editor.italic')
48862              }).render();
48863          });
48864          this.context.memo('button.underline', function () {
48865              return _this.button({
48866                  className: 'note-btn-underline',
48867                  contents: _this.ui.icon(_this.options.icons.underline),
48868                  tooltip: _this.lang.font.underline + _this.representShortcut('underline'),
48869                  click: _this.context.createInvokeHandlerAndUpdateState('editor.underline')
48870              }).render();
48871          });
48872          this.context.memo('button.clear', function () {
48873              return _this.button({
48874                  contents: _this.ui.icon(_this.options.icons.eraser),
48875                  tooltip: _this.lang.font.clear + _this.representShortcut('removeFormat'),
48876                  click: _this.context.createInvokeHandler('editor.removeFormat')
48877              }).render();
48878          });
48879          this.context.memo('button.strikethrough', function () {
48880              return _this.button({
48881                  className: 'note-btn-strikethrough',
48882                  contents: _this.ui.icon(_this.options.icons.strikethrough),
48883                  tooltip: _this.lang.font.strikethrough + _this.representShortcut('strikethrough'),
48884                  click: _this.context.createInvokeHandlerAndUpdateState('editor.strikethrough')
48885              }).render();
48886          });
48887          this.context.memo('button.superscript', function () {
48888              return _this.button({
48889                  className: 'note-btn-superscript',
48890                  contents: _this.ui.icon(_this.options.icons.superscript),
48891                  tooltip: _this.lang.font.superscript,
48892                  click: _this.context.createInvokeHandlerAndUpdateState('editor.superscript')
48893              }).render();
48894          });
48895          this.context.memo('button.subscript', function () {
48896              return _this.button({
48897                  className: 'note-btn-subscript',
48898                  contents: _this.ui.icon(_this.options.icons.subscript),
48899                  tooltip: _this.lang.font.subscript,
48900                  click: _this.context.createInvokeHandlerAndUpdateState('editor.subscript')
48901              }).render();
48902          });
48903          this.context.memo('button.fontname', function () {
vendor: 16,384 bytes, lines 48904-49222
48904              var styleInfo = _this.context.invoke('editor.currentStyle');
48905              // Add 'default' fonts into the fontnames array if not exist
48906              $$1.each(styleInfo['font-family'].split(','), function (idx, fontname) {
48907                  fontname = fontname.trim().replace(/['"]+/g, '');
48908                  if (_this.isFontDeservedToAdd(fontname)) {
48909                      if (_this.options.fontNames.indexOf(fontname) === -1) {
48910                          _this.options.fontNames.push(fontname);
48911                      }
48912                  }
48913              });
48914              return _this.ui.buttonGroup([
48915                  _this.button({
48916                      className: 'dropdown-toggle',
48917                      contents: _this.ui.dropdownButtonContents('<span class="note-current-fontname"/>', _this.options),
48918                      tooltip: _this.lang.font.name,
48919                      data: {
48920                          toggle: 'dropdown'
48921                      }
48922                  }),
48923                  _this.ui.dropdownCheck({
48924                      className: 'dropdown-fontname',
48925                      checkClassName: _this.options.icons.menuCheck,
48926                      items: _this.options.fontNames.filter(_this.isFontInstalled.bind(_this)),
48927                      title: _this.lang.font.name,
48928                      template: function (item) {
48929                          return '<span style="font-family: \'' + item + '\'">' + item + '</span>';
48930                      },
48931                      click: _this.context.createInvokeHandlerAndUpdateState('editor.fontName')
48932                  }),
48933              ]).render();
48934          });
48935          this.context.memo('button.fontsize', function () {
48936              return _this.ui.buttonGroup([
48937                  _this.button({
48938                      className: 'dropdown-toggle',
48939                      contents: _this.ui.dropdownButtonContents('<span class="note-current-fontsize"/>', _this.options),
48940                      tooltip: _this.lang.font.size,
48941                      data: {
48942                          toggle: 'dropdown'
48943                      }
48944                  }),
48945                  _this.ui.dropdownCheck({
48946                      className: 'dropdown-fontsize',
48947                      checkClassName: _this.options.icons.menuCheck,
48948                      items: _this.options.fontSizes,
48949                      title: _this.lang.font.size,
48950                      click: _this.context.createInvokeHandlerAndUpdateState('editor.fontSize')
48951                  }),
48952              ]).render();
48953          });
48954          this.context.memo('button.color', function () {
48955              return _this.colorPalette('note-color-all', _this.lang.color.recent, true, true);
48956          });
48957          this.context.memo('button.forecolor', function () {
48958              return _this.colorPalette('note-color-fore', _this.lang.color.foreground, false, true);
48959          });
48960          this.context.memo('button.backcolor', function () {
48961              return _this.colorPalette('note-color-back', _this.lang.color.background, true, false);
48962          });
48963          this.context.memo('button.ul', function () {
48964              return _this.button({
48965                  contents: _this.ui.icon(_this.options.icons.unorderedlist),
48966                  tooltip: _this.lang.lists.unordered + _this.representShortcut('insertUnorderedList'),
48967                  click: _this.context.createInvokeHandler('editor.insertUnorderedList')
48968              }).render();
48969          });
48970          this.context.memo('button.ol', function () {
48971              return _this.button({
48972                  contents: _this.ui.icon(_this.options.icons.orderedlist),
48973                  tooltip: _this.lang.lists.ordered + _this.representShortcut('insertOrderedList'),
48974                  click: _this.context.createInvokeHandler('editor.insertOrderedList')
48975              }).render();
48976          });
48977          var justifyLeft = this.button({
48978              contents: this.ui.icon(this.options.icons.alignLeft),
48979              tooltip: this.lang.paragraph.left + this.representShortcut('justifyLeft'),
48980              click: this.context.createInvokeHandler('editor.justifyLeft')
48981          });
48982          var justifyCenter = this.button({
48983              contents: this.ui.icon(this.options.icons.alignCenter),
48984              tooltip: this.lang.paragraph.center + this.representShortcut('justifyCenter'),
48985              click: this.context.createInvokeHandler('editor.justifyCenter')
48986          });
48987          var justifyRight = this.button({
48988              contents: this.ui.icon(this.options.icons.alignRight),
48989              tooltip: this.lang.paragraph.right + this.representShortcut('justifyRight'),
48990              click: this.context.createInvokeHandler('editor.justifyRight')
48991          });
48992          var justifyFull = this.button({
48993              contents: this.ui.icon(this.options.icons.alignJustify),
48994              tooltip: this.lang.paragraph.justify + this.representShortcut('justifyFull'),
48995              click: this.context.createInvokeHandler('editor.justifyFull')
48996          });
48997          var outdent = this.button({
48998              contents: this.ui.icon(this.options.icons.outdent),
48999              tooltip: this.lang.paragraph.outdent + this.representShortcut('outdent'),
49000              click: this.context.createInvokeHandler('editor.outdent')
49001          });
49002          var indent = this.button({
49003              contents: this.ui.icon(this.options.icons.indent),
49004              tooltip: this.lang.paragraph.indent + this.representShortcut('indent'),
49005              click: this.context.createInvokeHandler('editor.indent')
49006          });
49007          this.context.memo('button.justifyLeft', func.invoke(justifyLeft, 'render'));
49008          this.context.memo('button.justifyCenter', func.invoke(justifyCenter, 'render'));
49009          this.context.memo('button.justifyRight', func.invoke(justifyRight, 'render'));
49010          this.context.memo('button.justifyFull', func.invoke(justifyFull, 'render'));
49011          this.context.memo('button.outdent', func.invoke(outdent, 'render'));
49012          this.context.memo('button.indent', func.invoke(indent, 'render'));
49013          this.context.memo('button.paragraph', function () {
49014              return _this.ui.buttonGroup([
49015                  _this.button({
49016                      className: 'dropdown-toggle',
49017                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.alignLeft), _this.options),
49018                      tooltip: _this.lang.paragraph.paragraph,
49019                      data: {
49020                          toggle: 'dropdown'
49021                      }
49022                  }),
49023                  _this.ui.dropdown([
49024                      _this.ui.buttonGroup({
49025                          className: 'note-align',
49026                          children: [justifyLeft, justifyCenter, justifyRight, justifyFull]
49027                      }),
49028                      _this.ui.buttonGroup({
49029                          className: 'note-list',
49030                          children: [outdent, indent]
49031                      }),
49032                  ]),
49033              ]).render();
49034          });
49035          this.context.memo('button.height', function () {
49036              return _this.ui.buttonGroup([
49037                  _this.button({
49038                      className: 'dropdown-toggle',
49039                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.textHeight), _this.options),
49040                      tooltip: _this.lang.font.height,
49041                      data: {
49042                          toggle: 'dropdown'
49043                      }
49044                  }),
49045                  _this.ui.dropdownCheck({
49046                      items: _this.options.lineHeights,
49047                      checkClassName: _this.options.icons.menuCheck,
49048                      className: 'dropdown-line-height',
49049                      title: _this.lang.font.height,
49050                      click: _this.context.createInvokeHandler('editor.lineHeight')
49051                  }),
49052              ]).render();
49053          });
49054          this.context.memo('button.table', function () {
49055              return _this.ui.buttonGroup([
49056                  _this.button({
49057                      className: 'dropdown-toggle',
49058                      contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.table), _this.options),
49059                      tooltip: _this.lang.table.table,
49060                      data: {
49061                          toggle: 'dropdown'
49062                      }
49063                  }),
49064                  _this.ui.dropdown({
49065                      title: _this.lang.table.table,
49066                      className: 'note-table',
49067                      items: [
49068                          '<div class="note-dimension-picker">',
49069                          '  <div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"/>',
49070                          '  <div class="note-dimension-picker-highlighted"/>',
49071                          '  <div class="note-dimension-picker-unhighlighted"/>',
49072                          '</div>',
49073                          '<div class="note-dimension-display">1 x 1</div>',
49074                      ].join('')
49075                  }),
49076              ], {
49077                  callback: function ($node) {
49078                      var $catcher = $node.find('.note-dimension-picker-mousecatcher');
49079                      $catcher.css({
49080                          width: _this.options.insertTableMaxSize.col + 'em',
49081                          height: _this.options.insertTableMaxSize.row + 'em'
49082                      }).mousedown(_this.context.createInvokeHandler('editor.insertTable'))
49083                          .on('mousemove', _this.tableMoveHandler.bind(_this));
49084                  }
49085              }).render();
49086          });
49087          this.context.memo('button.link', function () {
49088              return _this.button({
49089                  contents: _this.ui.icon(_this.options.icons.link),
49090                  tooltip: _this.lang.link.link + _this.representShortcut('linkDialog.show'),
49091                  click: _this.context.createInvokeHandler('linkDialog.show')
49092              }).render();
49093          });
49094          this.context.memo('button.picture', function () {
49095              return _this.button({
49096                  contents: _this.ui.icon(_this.options.icons.picture),
49097                  tooltip: _this.lang.image.image,
49098                  click: _this.context.createInvokeHandler('imageDialog.show')
49099              }).render();
49100          });
49101          this.context.memo('button.video', function () {
49102              return _this.button({
49103                  contents: _this.ui.icon(_this.options.icons.video),
49104                  tooltip: _this.lang.video.video,
49105                  click: _this.context.createInvokeHandler('videoDialog.show')
49106              }).render();
49107          });
49108          this.context.memo('button.hr', function () {
49109              return _this.button({
49110                  contents: _this.ui.icon(_this.options.icons.minus),
49111                  tooltip: _this.lang.hr.insert + _this.representShortcut('insertHorizontalRule'),
49112                  click: _this.context.createInvokeHandler('editor.insertHorizontalRule')
49113              }).render();
49114          });
49115          this.context.memo('button.fullscreen', function () {
49116              return _this.button({
49117                  className: 'btn-fullscreen',
49118                  contents: _this.ui.icon(_this.options.icons.arrowsAlt),
49119                  tooltip: _this.lang.options.fullscreen,
49120                  click: _this.context.createInvokeHandler('fullscreen.toggle')
49121              }).render();
49122          });
49123          this.context.memo('button.codeview', function () {
49124              return _this.button({
49125                  className: 'btn-codeview',
49126                  contents: _this.ui.icon(_this.options.icons.code),
49127                  tooltip: _this.lang.options.codeview,
49128                  click: _this.context.createInvokeHandler('codeview.toggle')
49129              }).render();
49130          });
49131          this.context.memo('button.redo', function () {
49132              return _this.button({
49133                  contents: _this.ui.icon(_this.options.icons.redo),
49134                  tooltip: _this.lang.history.redo + _this.representShortcut('redo'),
49135                  click: _this.context.createInvokeHandler('editor.redo')
49136              }).render();
49137          });
49138          this.context.memo('button.undo', function () {
49139              return _this.button({
49140                  contents: _this.ui.icon(_this.options.icons.undo),
49141                  tooltip: _this.lang.history.undo + _this.representShortcut('undo'),
49142                  click: _this.context.createInvokeHandler('editor.undo')
49143              }).render();
49144          });
49145          this.context.memo('button.help', function () {
49146              return _this.button({
49147                  contents: _this.ui.icon(_this.options.icons.question),
49148                  tooltip: _this.lang.options.help,
49149                  click: _this.context.createInvokeHandler('helpDialog.show')
49150              }).render();
49151          });
49152      };
49153      /**
49154       * image: [
49155       *   ['imageResize', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
49156       *   ['float', ['floatLeft', 'floatRight', 'floatNone']],
49157       *   ['remove', ['removeMedia']],
49158       * ],
49159       */
49160      Buttons.prototype.addImagePopoverButtons = function () {
49161          var _this = this;
49162          // Image Size Buttons
49163          this.context.memo('button.resizeFull', function () {
49164              return _this.button({
49165                  contents: '<span class="note-fontsize-10">100%</span>',
49166                  tooltip: _this.lang.image.resizeFull,
49167                  click: _this.context.createInvokeHandler('editor.resize', '1')
49168              }).render();
49169          });
49170          this.context.memo('button.resizeHalf', function () {
49171              return _this.button({
49172                  contents: '<span class="note-fontsize-10">50%</span>',
49173                  tooltip: _this.lang.image.resizeHalf,
49174                  click: _this.context.createInvokeHandler('editor.resize', '0.5')
49175              }).render();
49176          });
49177          this.context.memo('button.resizeQuarter', function () {
49178              return _this.button({
49179                  contents: '<span class="note-fontsize-10">25%</span>',
49180                  tooltip: _this.lang.image.resizeQuarter,
49181                  click: _this.context.createInvokeHandler('editor.resize', '0.25')
49182              }).render();
49183          });
49184          this.context.memo('button.resizeNone', function () {
49185              return _this.button({
49186                  contents: _this.ui.icon(_this.options.icons.rollback),
49187                  tooltip: _this.lang.image.resizeNone,
49188                  click: _this.context.createInvokeHandler('editor.resize', '0')
49189              }).render();
49190          });
49191          // Float Buttons
49192          this.context.memo('button.floatLeft', function () {
49193              return _this.button({
49194                  contents: _this.ui.icon(_this.options.icons.floatLeft),
49195                  tooltip: _this.lang.image.floatLeft,
49196                  click: _this.context.createInvokeHandler('editor.floatMe', 'left')
49197              }).render();
49198          });
49199          this.context.memo('button.floatRight', function () {
49200              return _this.button({
49201                  contents: _this.ui.icon(_this.options.icons.floatRight),
49202                  tooltip: _this.lang.image.floatRight,
49203                  click: _this.context.createInvokeHandler('editor.floatMe', 'right')
49204              }).render();
49205          });
49206          this.context.memo('button.floatNone', function () {
49207              return _this.button({
49208                  contents: _this.ui.icon(_this.options.icons.rollback),
49209                  tooltip: _this.lang.image.floatNone,
49210                  click: _this.context.createInvokeHandler('editor.floatMe', 'none')
49211              }).render();
49212          });
49213          // Remove Buttons
49214          this.context.memo('button.removeMedia', function () {
49215              return _this.button({
49216                  contents: _this.ui.icon(_this.options.icons.trash),
49217                  tooltip: _this.lang.image.remove,
49218                  click: _this.context.createInvokeHandler('editor.removeMedia')
49219              }).render();
49220          });
49221      };
49222      Buttons.prototype.addLinkPopoverButtons = function () {
49223          var _this = this;
49224          this.context.memo('button.linkDialogShow', function () {
49225              return _this.button({
49226                  contents: _this.ui.icon(_this.options.icons.link),
49227                  tooltip: _this.lang.link.edit,
49228                  click: _this.context.createInvokeHandler('linkDialog.show')
49229              }).render();
49230          });
49231          this.context.memo('button.unlink', function () {
49232              return _this.button({
49233                  contents: _this.ui.icon(_this.options.icons.unlink),
49234                  tooltip: _this.lang.link.unlink,
49235                  click: _this.context.createInvokeHandler('editor.unlink')
49236              }).render();
49237          });
49238      };
49239      /**
49240       * table : [
49241       *  ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
49242       *  ['delete', ['deleteRow', 'deleteCol', 'deleteTable']]
49243       * ],
49244       */
49245      Buttons.prototype.addTablePopoverButtons = function () {
49246          var _this = this;
49247          this.context.memo('button.addRowUp', function () {
49248              return _this.button({
49249                  className: 'btn-md',
49250                  contents: _this.ui.icon(_this.options.icons.rowAbove),
49251                  tooltip: _this.lang.table.addRowAbove,
49252                  click: _this.context.createInvokeHandler('editor.addRow', 'top')
49253              }).render();
49254          });
49255          this.context.memo('button.addRowDown', function () {
49256              return _this.button({
49257                  className: 'btn-md',
49258                  contents: _this.ui.icon(_this.options.icons.rowBelow),
49259                  tooltip: _this.lang.table.addRowBelow,
49260                  click: _this.context.createInvokeHandler('editor.addRow', 'bottom')
49261              }).render();
49262          });
49263          this.context.memo('button.addColLeft', function () {
49264              return _this.button({
49265                  className: 'btn-md',
49266                  contents: _this.ui.icon(_this.options.icons.colBefore),
49267                  tooltip: _this.lang.table.addColLeft,
49268                  click: _this.context.createInvokeHandler('editor.addCol', 'left')
49269              }).render();
49270          });
49271          this.context.memo('button.addColRight', function () {
49272              return _this.button({
49273                  className: 'btn-md',
49274                  contents: _this.ui.icon(_this.options.icons.colAfter),
49275                  tooltip: _this.lang.table.addColRight,
49276                  click: _this.context.createInvokeHandler('editor.addCol', 'right')
49277              }).render();
49278          });
49279          this.context.memo('button.deleteRow', function () {
49280              return _this.button({
49281                  className: 'btn-md',
49282                  contents: _this.ui.icon(_this.options.icons.rowRemove),
49283                  tooltip: _this.lang.table.delRow,
49284                  click: _this.context.createInvokeHandler('editor.deleteRow')
49285              }).render();
49286          });
49287          this.context.memo('button.deleteCol', function () {
49288              return _this.button({
49289                  className: 'btn-md',
49290                  contents: _this.ui.icon(_this.options.icons.colRemove),
49291                  tooltip: _this.lang.table.delCol,
49292                  click: _this.context.createInvokeHandler('editor.deleteCol')
49293              }).render();
49294          });
49295          this.context.memo('button.deleteTable', function () {
49296              return _this.button({
49297                  className: 'btn-md',
49298                  contents: _this.ui.icon(_this.options.icons.trash),
49299                  tooltip: _this.lang.table.delTable,
49300                  click: _this.context.createInvokeHandler('editor.deleteTable')
49301              }).render();
49302          });
49303      };
49304      Buttons.prototype.build = function ($container, groups) {
49305          for (var groupIdx = 0, groupLen = groups.length; groupIdx < groupLen; groupIdx++) {
49306              var group = groups[groupIdx];
49307              var groupName = Array.isArray(group) ? group[0] : group;
49308              var buttons = Array.isArray(group) ? ((group.length === 1) ? [group[0]] : group[1]) : [group];
49309              var $group = this.ui.buttonGroup({
49310                  className: 'note-' + groupName
49311              }).render();
49312              for (var idx = 0, len = buttons.length; idx < len; idx++) {
49313                  var btn = this.context.memo('button.' + buttons[idx]);
49314                  if (btn) {
49315                      $group.append(typeof btn === 'function' ? btn() : btn);
49316                  }
49317              }
49318              $group.appendTo($container);
49319          }
49320      };
49321      /**
49322       * @param {jQuery} [$container]
49323       */
49324      Buttons.prototype.updateCurrentStyle = function ($container) {
49325          var _this = this;
49326          var $cont = $container || this.$toolbar;
49327          var styleInfo = this.context.invoke('editor.currentStyle');
49328          this.updateBtnStates($cont, {
49329              '.note-btn-bold': function () {
49330                  return styleInfo['font-bold'] === 'bold';
49331              },
49332              '.note-btn-italic': function () {
49333                  return styleInfo['font-italic'] === 'italic';
49334              },
49335              '.note-btn-underline': function () {
49336                  return styleInfo['font-underline'] === 'underline';
49337              },
49338              '.note-btn-subscript': function () {
49339                  return styleInfo['font-subscript'] === 'subscript';
49340              },
49341              '.note-btn-superscript': function () {
49342                  return styleInfo['font-superscript'] === 'superscript';
49343              },
49344              '.note-btn-strikethrough': function () {
49345                  return styleInfo['font-strikethrough'] === 'strikethrough';
49346              }
49347          });
49348          if (styleInfo['font-family']) {
49349              var fontNames = styleInfo['font-family'].split(',').map(function (name) {
49350                  return name.replace(/[\'\"]/g, '')
49351                      .replace(/\s+$/, '')
49352                      .replace(/^\s+/, '');
49353              });
49354              var fontName_1 = lists.find(fontNames, this.isFontInstalled.bind(this));
49355              $cont.find('.dropdown-fontname a').each(function (idx, item) {
49356                  var $item = $$1(item);
49357                  // always compare string to avoid creating another func.
49358                  var isChecked = ($item.data('value') + '') === (fontName_1 + '');
49359                  $item.toggleClass('checked', isChecked);
49360              });
49361              $cont.find('.note-current-fontname').text(fontName_1).css('font-family', fontName_1);
49362          }
49363          if (styleInfo['font-size']) {
49364              var fontSize_1 = styleInfo['font-size'];
49365              $cont.find('.dropdown-fontsize a').each(function (idx, item) {
49366                  var $item = $$1(item);
49367                  // always compare with string to avoid creating another func.
49368                  var isChecked = ($item.data('value') + '') === (fontSize_1 + '');
49369                  $item.toggleClass('checked', isChecked);
49370              });
49371              $cont.find('.note-current-fontsize').text(fontSize_1);
49372          }
49373          if (styleInfo['line-height']) {
49374              var lineHeight_1 = styleInfo['line-height'];
49375              $cont.find('.dropdown-line-height li a').each(function (idx, item) {
49376                  // always compare with string to avoid creating another func.
49377                  var isChecked = ($$1(item).data('value') + '') === (lineHeight_1 + '');
49378                  _this.className = isChecked ? 'checked' : '';
49379              });
49380          }
49381      };
49382      Buttons.prototype.updateBtnStates = function ($container, infos) {
49383          var _this = this;
49384          $$1.each(infos, function (selector, pred) {
49385              _this.ui.toggleBtnActive($container.find(selector), pred());
49386          });
49387      };
49388      Buttons.prototype.tableMoveHandler = function (event) {
49389          var PX_PER_EM = 18;
49390          var $picker = $$1(event.target.parentNode); // target is mousecatcher
49391          var $dimensionDisplay = $picker.next();
49392          var $catcher = $picker.find('.note-dimension-picker-mousecatcher');
49393          var $highlighted = $picker.find('.note-dimension-picker-highlighted');
49394          var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted');
49395          var posOffset;
49396          // HTML5 with jQuery - e.offsetX is undefined in Firefox
49397          if (event.offsetX === undefined) {
49398              var posCatcher = $$1(event.target).offset();
49399              posOffset = {
49400                  x: event.pageX - posCatcher.left,
49401                  y: event.pageY - posCatcher.top
49402              };
49403          }
49404          else {
49405              posOffset = {
49406                  x: event.offsetX,
49407                  y: event.offsetY
49408              };
49409          }
49410          var dim = {
49411              c: Math.ceil(posOffset.x / PX_PER_EM) || 1,
49412              r: Math.ceil(posOffset.y / PX_PER_EM) || 1
49413          };
49414          $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' });
49415          $catcher.data('value', dim.c + 'x' + dim.r);
49416          if (dim.c > 3 && dim.c < this.options.insertTableMaxSize.col) {
49417              $unhighlighted.css({ width: dim.c + 1 + 'em' });
49418          }
49419          if (dim.r > 3 && dim.r < this.options.insertTableMaxSize.row) {
49420              $unhighlighted.css({ height: dim.r + 1 + 'em' });
49421          }
49422          $dimensionDisplay.html(dim.c + ' x ' + dim.r);
49423      };
49424      return Buttons;
49425  }());
49426
49427  var Toolbar = /** @class */ (function () {
49428      function Toolbar(context) {
49429          this.context = context;
49430          this.$window = $$1(window);
49431          this.$document = $$1(document);
49432          this.ui = $$1.summernote.ui;
49433          this.$note = context.layoutInfo.note;
49434          this.$editor = context.layoutInfo.editor;
49435          this.$toolbar = context.layoutInfo.toolbar;
49436          this.$editable = context.layoutInfo.editable;
49437          this.$statusbar = context.layoutInfo.statusbar;
49438          this.options = context.options;
49439          this.isFollowing = false;
49440          this.followScroll = this.followScroll.bind(this);
49441      }
49442      Toolbar.prototype.shouldInitialize = function () {
49443          return !this.options.airMode;
49444      };
49445      Toolbar.prototype.initialize = function () {
49446          var _this = this;
49447          this.options.toolbar = this.options.toolbar || [];
49448          if (!this.options.toolbar.length) {
49449              this.$toolbar.hide();
49450          }
49451          else {
49452              this.context.invoke('buttons.build', this.$toolbar, this.options.toolbar);
49453          }
49454          if (this.options.toolbarContainer) {
49455              this.$toolbar.appendTo(this.options.toolbarContainer);
49456          }
49457          this.changeContainer(false);
49458          this.$note.on('summernote.keyup summernote.mouseup summernote.change', function () {
49459              _this.context.invoke('buttons.updateCurrentStyle');
49460          });
49461          this.context.invoke('buttons.updateCurrentStyle');
49462          if (this.options.followingToolbar) {
49463              this.$window.on('scroll resize', this.followScroll);
49464          }
49465      };
49466      Toolbar.prototype.destroy = function () {
49467          this.$toolbar.children().remove();
49468          if (this.options.followingToolbar) {
49469              this.$window.off('scroll resize', this.followScroll);
49470          }
49471      };
49472      Toolbar.prototype.followScroll = function () {
49473          if (this.$editor.hasClass('fullscreen')) {
49474              return false;
49475          }
49476          var editorHeight = this.$editor.outerHeight();
49477          var editorWidth = this.$editor.width();
49478          var toolbarHeight = this.$toolbar.height();
49479          var statusbarHeight = this.$statusbar.height();
49480          // check if the web app is currently using another static bar
49481          var otherBarHeight = 0;
49482          if (this.options.otherStaticBar) {
49483              otherBarHeight = $$1(this.options.otherStaticBar).outerHeight();
49484          }
49485          var currentOffset = this.$document.scrollTop();
49486          var editorOffsetTop = this.$editor.offset().top;
49487          var editorOffsetBottom = editorOffsetTop + editorHeight;
49488          var activateOffset = editorOffsetTop - otherBarHeight;
49489          var deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight - statusbarHeight;
49490          if (!this.isFollowing &&
49491              (currentOffset > activateOffset) && (currentOffset < deactivateOffsetBottom - toolbarHeight)) {
49492              this.isFollowing = true;
49493              this.$toolbar.css({
49494                  position: 'fixed',
49495                  top: otherBarHeight,
49496                  width: editorWidth
49497              });
49498              this.$editable.css({
49499                  marginTop: this.$toolbar.height() + 5
49500              });
49501          }
49502          else if (this.isFollowing &&
49503              ((currentOffset < activateOffset) || (currentOffset > deactivateOffsetBottom))) {
49504              this.isFollowing = false;
49505              this.$toolbar.css({
49506                  position: 'relative',
49507                  top: 0,
49508                  width: '100%'
49509              });
49510              this.$editable.css({
49511                  marginTop: ''
49512              });
49513          }
49514      };
49515      Toolbar.prototype.changeContainer = function (isFullscreen) {
49516          if (isFullscreen) {
49517              this.$toolbar.prependTo(this.$editor);
49518          }
49519          else {
49520              if (this.options.toolbarContainer) {
49521                  this.$toolbar.appendTo(this.options.toolbarContainer);
49522              }
49523          }
49524          this.followScroll();
49525      };
49526      Toolbar.prototype.updateFullscreen = function (isFullscreen) {
49527          this.ui.toggleBtnActive(this.$toolbar.find('.btn-fullscreen'), isFullscreen);
49528          this.changeContainer(isFullscreen);
49529      };
49530      Toolbar.prototype.updateCodeview = function (isCodeview) {
49531          this.ui.toggleBtnActive(this.$toolbar.find('.btn-codeview'), isCodeview);
49532          if (isCodeview) {
49533              this.deactivate();
49534          }
49535          else {
49536              this.activate();
49537          }
49538      };
49539      Toolbar.prototype.activate = function (isIncludeCodeview) {
49540          var $btn = this.$toolbar.find('button');
49541          if (!isIncludeCodeview) {
49542              $btn = $btn.not('.btn-codeview');
49543          }
49544          this.ui.toggleBtn($btn, true);
49545      };
49546      Toolbar.prototype.deactivate = function (isIncludeCodeview) {
49547          var $btn = this.$toolbar.find('button');
49548          if (!isIncludeCodeview) {
49549              $btn = $btn.not('.btn-codeview');
49550          }
49551          this.ui.toggleBtn($btn, false);
49552      };
49553      return Toolbar;
49554  }());
49555
49556  var LinkDialog = /** @class */ (function () {
49557      function LinkDialog(context) {
49558          this.context = context;
49559          this.ui = $$1.summernote.ui;
49560          this.$body = $$1(document.body);
49561          this.$editor = context.layoutInfo.editor;
49562          this.options = context.options;
49563          this.lang = this.options.langInfo;
49564          context.memo('help.linkDialog.show', this.options.langInfo.help['linkDialog.show']);
49565      }
49566      LinkDialog.prototype.initialize = function () {
49567          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
49568          var body = [
49569              '<div class="form-group note-form-group">',
49570              "<label class=\"note-form-label\">" + this.lang.link.textToDisplay + "</label>",
49571              '<input class="note-link-text form-control note-form-control note-input" type="text" />',
49572              '</div>',
49573              '<div class="form-group note-form-group">',
49574              "<label class=\"note-form-label\">" + this.lang.link.url + "</label>",
49575              '<input class="note-link-url form-control note-form-control note-input" type="text" value="http://" />',
49576              '</div>',
49577              !this.options.disableLinkTarget
49578                  ? $$1('<div/>').append(this.ui.checkbox({
49579                      className: 'sn-checkbox-open-in-new-window',
49580                      text: this.lang.link.openInNewWindow,
49581                      checked: true
49582                  }).render()).html()
49583                  : '',
49584          ].join('');
49585          var buttonClass = 'btn btn-primary note-btn note-btn-primary note-link-btn';
49586          var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.link.insert + "\" disabled>";
49587          this.$dialog = this.ui.dialog({
49588              className: 'link-dialog',
49589              title: this.lang.link.insert,
49590              fade: this.options.dialogsFade,
49591              body: body,
49592              footer: footer
49593          }).render().appendTo($container);
49594      };
49595      LinkDialog.prototype.destroy = function () {
49596          this.ui.hideDialog(this.$dialog);
49597          this.$dialog.remove();
49598      };
49599      LinkDialog.prototype.bindEnterKey = function ($input, $btn) {
49600          $input.on('keypress', function (event) {
49601              if (event.keyCode === key.code.ENTER) {
49602                  event.preventDefault();
49603                  $btn.trigger('click');
49604              }
49605          });
49606      };
49607      /**
49608       * toggle update button
49609       */
49610      LinkDialog.prototype.toggleLinkBtn = function ($linkBtn, $linkText, $linkUrl) {
49611          this.ui.toggleBtn($linkBtn, $linkText.val() && $linkUrl.val());
49612      };
49613      /**
49614       * Show link dialog and set event handlers on dialog controls.
49615       *
49616       * @param {Object} linkInfo
49617       * @return {Promise}
49618       */
49619      LinkDialog.prototype.showLinkDialog = function (linkInfo) {
49620          var _this = this;
49621          return $$1.Deferred(function (deferred) {
49622              var $linkText = _this.$dialog.find('.note-link-text');
49623              var $linkUrl = _this.$dialog.find('.note-link-url');
49624              var $linkBtn = _this.$dialog.find('.note-link-btn');
49625              var $openInNewWindow = _this.$dialog
49626                  .find('.sn-checkbox-open-in-new-window input[type=checkbox]');
49627              _this.ui.onDialogShown(_this.$dialog, function () {
49628                  _this.context.triggerEvent('dialog.shown');
49629                  // If no url was given and given text is valid URL then copy that into URL Field
49630                  if (!linkInfo.url && func.isValidUrl(linkInfo.text)) {
49631                      linkInfo.url = linkInfo.text;
49632                  }
49633                  $linkText.on('input paste propertychange', function () {
49634                      // If linktext was modified by input events,
49635                      // cloning text from linkUrl will be stopped.
49636                      linkInfo.text = $linkText.val();
49637                      _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
49638                  }).val(linkInfo.text);
49639                  $linkUrl.on('input paste propertychange', function () {
49640                      // Display same text on `Text to display` as default
49641                      // when linktext has no text
49642                      if (!linkInfo.text) {
49643                          $linkText.val($linkUrl.val());
49644                      }
49645                      _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
49646                  }).val(linkInfo.url);
49647                  if (!env.isSupportTouch) {
49648                      $linkUrl.trigger('focus');
49649                  }
49650                  _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl);
49651                  _this.bindEnterKey($linkUrl, $linkBtn);
49652                  _this.bindEnterKey($linkText, $linkBtn);
49653                  var isNewWindowChecked = linkInfo.isNewWindow !== undefined
49654                      ? linkInfo.isNewWindow : _this.context.options.linkTargetBlank;
49655                  $openInNewWindow.prop('checked', isNewWindowChecked);
49656                  $linkBtn.one('click', function (event) {
49657                      event.preventDefault();
49658                      deferred.resolve({
49659                          range: linkInfo.range,
49660                          url: $linkUrl.val(),
49661                          text: $linkText.val(),
49662                          isNewWindow: $openInNewWindow.is(':checked')
49663                      });
49664                      _this.ui.hideDialog(_this.$dialog);
49665                  });
49666              });
49667              _this.ui.onDialogHidden(_this.$dialog, function () {
49668                  // detach events
49669                  $linkText.off();
49670                  $linkUrl.off();
49671                  $linkBtn.off();
49672                  if (deferred.state() === 'pending') {
49673                      deferred.reject();
49674                  }
49675              });
49676              _this.ui.showDialog(_this.$dialog);
49677          }).promise();
49678      };
49679      /**
49680       * @param {Object} layoutInfo
49681       */
49682      LinkDialog.prototype.show = function () {
49683          var _this = this;
49684          var linkInfo = this.context.invoke('editor.getLinkInfo');
49685          this.context.invoke('editor.saveRange');
49686          this.showLinkDialog(linkInfo).then(function (linkInfo) {
49687              _this.context.invoke('editor.restoreRange');
49688              _this.context.invoke('editor.createLink', linkInfo);
49689          }).fail(function () {
49690              _this.context.invoke('editor.restoreRange');
49691          });
49692      };
49693      return LinkDialog;
49694  }());
49695
49696  var LinkPopover = /** @class */ (function () {
49697      function LinkPopover(context) {
49698          var _this = this;
49699          this.context = context;
49700          this.ui = $$1.summernote.ui;
49701          this.options = context.options;
49702          this.events = {
49703              'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function () {
49704                  _this.update();
49705              },
49706              'summernote.disable summernote.dialog.shown': function () {
49707                  _this.hide();
49708              }
49709          };
49710      }
49711      LinkPopover.prototype.shouldInitialize = function () {
49712          return !lists.isEmpty(this.options.popover.link);
49713      };
49714      LinkPopover.prototype.initialize = function () {
49715          this.$popover = this.ui.popover({
49716              className: 'note-link-popover',
49717              callback: function ($node) {
49718                  var $content = $node.find('.popover-content,.note-popover-content');
49719                  $content.prepend('<span><a target="_blank"></a>&nbsp;</span>');
49720              }
49721          }).render().appendTo(this.options.container);
49722          var $content = this.$popover.find('.popover-content,.note-popover-content');
49723          this.context.invoke('buttons.build', $content, this.options.popover.link);
49724      };
49725      LinkPopover.prototype.destroy = function () {
49726          this.$popover.remove();
49727      };
49728      LinkPopover.prototype.update = function () {
49729          // Prevent focusing on editable when invoke('code') is executed
49730          if (!this.context.invoke('editor.hasFocus')) {
49731              this.hide();
49732              return;
49733          }
49734          var rng = this.context.invoke('editor.getLastRange');
49735          if (rng.isCollapsed() && rng.isOnAnchor()) {
49736              var anchor = dom.ancestor(rng.sc, dom.isAnchor);
49737              var href = $$1(anchor).attr('href');
49738              this.$popover.find('a').attr('href', href).html(href);
49739              var pos = dom.posFromPlaceholder(anchor);
49740              this.$popover.css({
49741                  display: 'block',
49742                  left: pos.left,
49743                  top: pos.top
49744              });
49745          }
49746          else {
49747              this.hide();
49748          }
49749      };
49750      LinkPopover.prototype.hide = function () {
49751          this.$popover.hide();
49752      };
49753      return LinkPopover;
49754  }());
49755
49756  var ImageDialog = /** @class */ (function () {
49757      function ImageDialog(context) {
49758          this.context = context;
49759          this.ui = $$1.summernote.ui;
49760          this.$body = $$1(document.body);
49761          this.$editor = context.layoutInfo.editor;
49762          this.options = context.options;
49763          this.lang = this.options.langInfo;
49764      }
49765      ImageDialog.prototype.initialize = function () {
49766          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
49767          var imageLimitation = '';
49768          if (this.options.maximumImageFileSize) {
49769              var unit = Math.floor(Math.log(this.options.maximumImageFileSize) / Math.log(1024));
49770              var readableSize = (this.options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +
49771                  ' ' + ' KMGTP'[unit] + 'B';
49772              imageLimitation = "<small>" + (this.lang.image.maximumFileSize + ' : ' + readableSize) + "</small>";
49773          }
49774          var body = [
49775              '<div class="form-group note-form-group note-group-select-from-files">',
49776              '<label class="note-form-label">' + this.lang.image.selectFromFiles + '</label>',
49777              '<input class="note-image-input form-control-file note-form-control note-input" ',
49778              ' type="file" name="files" accept="image/*" multiple="multiple" />',
49779              imageLimitation,
49780              '</div>',
49781              '<div class="form-group note-group-image-url" style="overflow:auto;">',
49782              '<label class="note-form-label">' + this.lang.image.url + '</label>',
49783              '<input class="note-image-url form-control note-form-control note-input ',
49784              ' col-md-12" type="text" />',
49785              '</div>',
49786          ].join('');
49787          var buttonClass = 'btn btn-primary note-btn note-btn-primary note-image-btn';
49788          var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.image.insert + "\" disabled>";
49789          this.$dialog = this.ui.dialog({
49790              title: this.lang.image.insert,
49791              fade: this.options.dialogsFade,
49792              body: body,
49793              footer: footer
49794          }).render().appendTo($container);
49795      };
49796      ImageDialog.prototype.destroy = function () {
49797          this.ui.hideDialog(this.$dialog);
49798          this.$dialog.remove();
49799      };
49800      ImageDialog.prototype.bindEnterKey = function ($input, $btn) {
49801          $input.on('keypress', function (event) {
49802              if (event.keyCode === key.code.ENTER) {
49803                  event.preventDefault();
49804                  $btn.trigger('click');
49805              }
49806          });
49807      };
49808      ImageDialog.prototype.show = function () {
49809          var _this = this;
49810          this.context.invoke('editor.saveRange');
49811          this.showImageDialog().then(function (data) {
49812              // [workaround] hide dialog before restore range for IE range focus
49813              _this.ui.hideDialog(_this.$dialog);
49814              _this.context.invoke('editor.restoreRange');
49815              if (typeof data === 'string') { // image url
49816                  // If onImageLinkInsert set,
49817                  if (_this.options.callbacks.onImageLinkInsert) {
49818                      _this.context.triggerEvent('image.link.insert', data);
49819                  }
49820                  else {
49821                      _this.context.invoke('editor.insertImage', data);
49822                  }
49823              }
49824              else { // array of files
49825                  _this.context.invoke('editor.insertImagesOrCallback', data);
49826              }
49827          }).fail(function () {
49828              _this.context.invoke('editor.restoreRange');
49829          });
49830      };
49831      /**
49832       * show image dialog
49833       *
49834       * @param {jQuery} $dialog
49835       * @return {Promise}
49836       */
49837      ImageDialog.prototype.showImageDialog = function () {
49838          var _this = this;
49839          return $$1.Deferred(function (deferred) {
49840              var $imageInput = _this.$dialog.find('.note-image-input');
49841              var $imageUrl = _this.$dialog.find('.note-image-url');
49842              var $imageBtn = _this.$dialog.find('.note-image-btn');
49843              _this.ui.onDialogShown(_this.$dialog, function () {
49844                  _this.context.triggerEvent('dialog.shown');
49845                  // Cloning imageInput to clear element.
49846                  $imageInput.replaceWith($imageInput.clone().on('change', function (event) {
49847                      deferred.resolve(event.target.files || event.target.value);
49848                  }).val(''));
49849                  $imageUrl.on('input paste propertychange', function () {
49850                      _this.ui.toggleBtn($imageBtn, $imageUrl.val());
49851                  }).val('');
49852                  if (!env.isSupportTouch) {
49853                      $imageUrl.trigger('focus');
49854                  }
49855                  $imageBtn.click(function (event) {
49856                      event.preventDefault();
49857                      deferred.resolve($imageUrl.val());
49858                  });
49859                  _this.bindEnterKey($imageUrl, $imageBtn);
49860              });
49861              _this.ui.onDialogHidden(_this.$dialog, function () {
49862                  $imageInput.off();
49863                  $imageUrl.off();
49864                  $imageBtn.off();
49865                  if (deferred.state() === 'pending') {
49866                      deferred.reject();
49867                  }
49868              });
49869              _this.ui.showDialog(_this.$dialog);
49870          });
49871      };
49872      return ImageDialog;
49873  }());
49874
49875  /**
49876   * Image popover module
49877   *  mouse events that show/hide popover will be handled by Handle.js.
49878   *  Handle.js will receive the events and invoke 'imagePopover.update'.
49879   */
49880  var ImagePopover = /** @class */ (function () {
49881      function ImagePopover(context) {
49882          var _this = this;
49883          this.context = context;
49884          this.ui = $$1.summernote.ui;
49885          this.editable = context.layoutInfo.editable[0];
49886          this.options = context.options;
49887          this.events = {
49888              'summernote.disable': function () {
49889                  _this.hide();
49890              }
49891          };
49892      }
49893      ImagePopover.prototype.shouldInitialize = function () {
49894          return !lists.isEmpty(this.options.popover.image);
49895      };
49896      ImagePopover.prototype.initialize = function () {
49897          this.$popover = this.ui.popover({
49898              className: 'note-image-popover'
49899          }).render().appendTo(this.options.container);
49900          var $content = this.$popover.find('.popover-content,.note-popover-content');
49901          this.context.invoke('buttons.build', $content, this.options.popover.image);
49902      };
49903      ImagePopover.prototype.destroy = function () {
49904          this.$popover.remove();
49905      };
49906      ImagePopover.prototype.update = function (target, event) {
49907          if (dom.isImg(target)) {
49908              var pos = dom.posFromPlaceholder(target);
49909              var posEditor = dom.posFromPlaceholder(this.editable);
49910              this.$popover.css({
49911                  display: 'block',
49912                  left: this.options.popatmouse ? event.pageX - 20 : pos.left,
49913                  top: this.options.popatmouse ? event.pageY -50 : Math.min(pos.top, posEditor.top)
49914              });
49915          }
49916          else {
49917              this.hide();
49918          }
49919      };
49920      ImagePopover.prototype.hide = function () {
49921          this.$popover.hide();
49922      };
49923      return ImagePopover;
49924  }());
49925
49926  var TablePopover = /** @class */ (function () {
49927      function TablePopover(context) {
49928          var _this = this;
49929          this.context = context;
49930          this.ui = $$1.summernote.ui;
49931          this.options = context.options;
49932          this.events = {
49933              'summernote.mousedown': function (we, e) {
49934                  _this.update(e.target);
49935              },
49936              'summernote.keyup summernote.scroll summernote.change': function () {
49937                  _this.update();
49938              },
49939              'summernote.disable': function () {
49940                  _this.hide();
49941              }
49942          };
49943      }
49944      TablePopover.prototype.shouldInitialize = function () {
49945          return !lists.isEmpty(this.options.popover.table);
49946      };
49947      TablePopover.prototype.initialize = function () {
49948          this.$popover = this.ui.popover({
49949              className: 'note-table-popover'
49950          }).render().appendTo(this.options.container);
49951          var $content = this.$popover.find('.popover-content,.note-popover-content');
49952          this.context.invoke('buttons.build', $content, this.options.popover.table);
49953          // [workaround] Disable Firefox's default table editor
49954          if (env.isFF) {
49955              document.execCommand('enableInlineTableEditing', false, false);
49956          }
49957      };
49958      TablePopover.prototype.destroy = function () {
49959          this.$popover.remove();
49960      };
49961      TablePopover.prototype.update = function (target) {
49962          if (this.context.isDisabled()) {
49963              return false;
49964          }
49965          var isCell = dom.isCell(target);
49966          if (isCell) {
49967              var pos = dom.posFromPlaceholder(target);
49968              this.$popover.css({
49969                  display: 'block',
49970                  left: pos.left,
49971                  top: pos.top
49972              });
49973          }
49974          else {
49975              this.hide();
49976          }
49977          return isCell;
49978      };
49979      TablePopover.prototype.hide = function () {
49980          this.$popover.hide();
49981      };
49982      return TablePopover;
49983  }());
49984
49985  var VideoDialog = /** @class */ (function () {
49986      function VideoDialog(context) {
49987          this.context = context;
49988          this.ui = $$1.summernote.ui;
49989          this.$body = $$1(document.body);
49990          this.$editor = context.layoutInfo.editor;
49991          this.options = context.options;
49992          this.lang = this.options.langInfo;
49993      }
49994      VideoDialog.prototype.initialize = function () {
49995          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
49996          var body = [
49997              '<div class="form-group note-form-group row-fluid">',
49998              "<label class=\"note-form-label\">" + this.lang.video.url + " <small class=\"text-muted\">" + this.lang.video.providers + "</small></label>",
49999              '<input class="note-video-url form-control note-form-control note-input" type="text" />',
50000              '</div>',
50001          ].join('');
50002          var buttonClass = 'btn btn-primary note-btn note-btn-primary note-video-btn';
50003          var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.video.insert + "\" disabled>";
50004          this.$dialog = this.ui.dialog({
50005              title: this.lang.video.insert,
50006              fade: this.options.dialogsFade,
50007              body: body,
50008              footer: footer
50009          }).render().appendTo($container);
50010      };
50011      VideoDialog.prototype.destroy = function () {
50012          this.ui.hideDialog(this.$dialog);
50013          this.$dialog.remove();
50014      };
50015      VideoDialog.prototype.bindEnterKey = function ($input, $btn) {
50016          $input.on('keypress', function (event) {
50017              if (event.keyCode === key.code.ENTER) {
50018                  event.preventDefault();
50019                  $btn.trigger('click');
50020              }
50021          });
50022      };
50023      VideoDialog.prototype.createVideoNode = function (url) {
50024          // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)
50025          var ytRegExp = /\/\/(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([\w|-]{11})(?:(?:[\?&]t=)(\S+))?$/;
50026          var ytRegExpForStart = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
50027          var ytMatch = url.match(ytRegExp);
50028          var igRegExp = /(?:www\.|\/\/)instagram\.com\/p\/(.[a-zA-Z0-9_-]*)/;
50029          var igMatch = url.match(igRegExp);
50030          var vRegExp = /\/\/vine\.co\/v\/([a-zA-Z0-9]+)/;
50031          var vMatch = url.match(vRegExp);
50032          var vimRegExp = /\/\/(player\.)?vimeo\.com\/([a-z]*\/)*(\d+)[?]?.*/;
50033          var vimMatch = url.match(vimRegExp);
50034          var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/;
50035          var dmMatch = url.match(dmRegExp);
50036          var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/;
50037          var youkuMatch = url.match(youkuRegExp);
50038          var qqRegExp = /\/\/v\.qq\.com.*?vid=(.+)/;
50039          var qqMatch = url.match(qqRegExp);
50040          var qqRegExp2 = /\/\/v\.qq\.com\/x?\/?(page|cover).*?\/([^\/]+)\.html\??.*/;
50041          var qqMatch2 = url.match(qqRegExp2);
50042          var mp4RegExp = /^.+.(mp4|m4v)$/;
50043          var mp4Match = url.match(mp4RegExp);
50044          var oggRegExp = /^.+.(ogg|ogv)$/;
50045          var oggMatch = url.match(oggRegExp);
50046          var webmRegExp = /^.+.(webm)$/;
50047          var webmMatch = url.match(webmRegExp);
50048          var fbRegExp = /(?:www\.|\/\/)facebook\.com\/([^\/]+)\/videos\/([0-9]+)/;
50049          var fbMatch = url.match(fbRegExp);
50050          var $video;
50051          if (ytMatch && ytMatch[1].length === 11) {
50052              var youtubeId = ytMatch[1];
50053              var start = 0;
50054              if (typeof ytMatch[2] !== 'undefined') {
50055                  var ytMatchForStart = ytMatch[2].match(ytRegExpForStart);
50056                  if (ytMatchForStart) {
50057                      for (var n = [3600, 60, 1], i = 0, r = n.length; i < r; i++) {
50058                          start += (typeof ytMatchForStart[i + 1] !== 'undefined' ? n[i] * parseInt(ytMatchForStart[i + 1], 10) : 0);
50059                      }
50060                  }
50061              }
50062              $video = $$1('<iframe>')
50063                  .attr('frameborder', 0)
50064                  .attr('src', '//www.youtube.com/embed/' + youtubeId + (start > 0 ? '?start=' + start : ''))
50065                  .attr('width', '640').attr('height', '360');
50066          }
50067          else if (igMatch && igMatch[0].length) {
50068              $video = $$1('<iframe>')
50069                  .attr('frameborder', 0)
50070                  .attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/')
50071                  .attr('width', '612').attr('height', '710')
50072                  .attr('scrolling', 'no')
50073                  .attr('allowtransparency', 'true');
50074          }
50075          else if (vMatch && vMatch[0].length) {
50076              $video = $$1('<iframe>')
50077                  .attr('frameborder', 0)
50078                  .attr('src', vMatch[0] + '/embed/simple')
50079                  .attr('width', '600').attr('height', '600')
50080                  .attr('class', 'vine-embed');
50081          }
50082          else if (vimMatch && vimMatch[3].length) {
50083              $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
50084                  .attr('frameborder', 0)
50085                  .attr('src', '//player.vimeo.com/video/' + vimMatch[3])
50086                  .attr('width', '640').attr('height', '360');
50087          }
50088          else if (dmMatch && dmMatch[2].length) {
50089              $video = $$1('<iframe>')
50090                  .attr('frameborder', 0)
50091                  .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])
50092                  .attr('width', '640').attr('height', '360');
50093          }
50094          else if (youkuMatch && youkuMatch[1].length) {
50095              $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
50096                  .attr('frameborder', 0)
50097                  .attr('height', '498')
50098                  .attr('width', '510')
50099                  .attr('src', '//player.youku.com/embed/' + youkuMatch[1]);
50100          }
50101          else if ((qqMatch && qqMatch[1].length) || (qqMatch2 && qqMatch2[2].length)) {
50102              var vid = ((qqMatch && qqMatch[1].length) ? qqMatch[1] : qqMatch2[2]);
50103              $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
50104                  .attr('frameborder', 0)
50105                  .attr('height', '310')
50106                  .attr('width', '500')
50107                  .attr('src', 'http://v.qq.com/iframe/player.html?vid=' + vid + '&amp;auto=0');
50108          }
50109          else if (mp4Match || oggMatch || webmMatch) {
50110              $video = $$1('<video controls>')
50111                  .attr('src', url)
50112                  .attr('width', '640').attr('height', '360');
50113          }
50114          else if (fbMatch && fbMatch[0].length) {
50115              $video = $$1('<iframe>')
50116                  .attr('frameborder', 0)
50117                  .attr('src', 'https://www.facebook.com/plugins/video.php?href=' + encodeURIComponent(fbMatch[0]) + '&show_text=0&width=560')
50118                  .attr('width', '560').attr('height', '301')
50119                  .attr('scrolling', 'no')
50120                  .attr('allowtransparency', 'true');
50121          }
50122          else {
50123              // this is not a known video link. Now what, Cat? Now what?
50124              return false;
50125          }
50126          $video.addClass('note-video-clip');
50127          return $video[0];
50128      };
50129      VideoDialog.prototype.show = function () {
50130          var _this = this;
50131          var text = this.context.invoke('editor.getSelectedText');
50132          this.context.invoke('editor.saveRange');
50133          this.showVideoDialog(text).then(function (url) {
50134              // [workaround] hide dialog before restore range for IE range focus
50135              _this.ui.hideDialog(_this.$dialog);
50136              _this.context.invoke('editor.restoreRange');
50137              // build node
50138              var $node = _this.createVideoNode(url);
50139              if ($node) {
50140                  // insert video node
50141                  _this.context.invoke('editor.insertNode', $node);
50142              }
50143          }).fail(function () {
50144              _this.context.invoke('editor.restoreRange');
50145          });
50146      };
50147      /**
50148       * show image dialog
50149       *
50150       * @param {jQuery} $dialog
50151       * @return {Promise}
50152       */
50153      VideoDialog.prototype.showVideoDialog = function (text) {
50154          var _this = this;
50155          return $$1.Deferred(function (deferred) {
50156              var $videoUrl = _this.$dialog.find('.note-video-url');
50157              var $videoBtn = _this.$dialog.find('.note-video-btn');
50158              _this.ui.onDialogShown(_this.$dialog, function () {
50159                  _this.context.triggerEvent('dialog.shown');
50160                  $videoUrl.on('input paste propertychange', function () {
50161                      _this.ui.toggleBtn($videoBtn, $videoUrl.val());
50162                  });
50163                  if (!env.isSupportTouch) {
50164                      $videoUrl.trigger('focus');
50165                  }
50166                  $videoBtn.click(function (event) {
50167                      event.preventDefault();
50168                      deferred.resolve($videoUrl.val());
50169                  });
50170                  _this.bindEnterKey($videoUrl, $videoBtn);
50171              });
50172              _this.ui.onDialogHidden(_this.$dialog, function () {
50173                  $videoUrl.off();
50174                  $videoBtn.off();
50175                  if (deferred.state() === 'pending') {
50176                      deferred.reject();
50177                  }
50178              });
50179              _this.ui.showDialog(_this.$dialog);
50180          });
50181      };
50182      return VideoDialog;
50183  }());
50184
50185  var HelpDialog = /** @class */ (function () {
50186      function HelpDialog(context) {
50187          this.context = context;
50188          this.ui = $$1.summernote.ui;
50189          this.$body = $$1(document.body);
50190          this.$editor = context.layoutInfo.editor;
50191          this.options = context.options;
50192          this.lang = this.options.langInfo;
50193      }
50194      HelpDialog.prototype.initialize = function () {
50195          var $container = this.options.dialogsInBody ? this.$body : this.$editor;
50196          var body = [
50197              '<p class="text-center">',
50198              '<a href="http://summernote.org/" target="_blank">Summernote 0.8.12</a> · ',
50199              '<a href="https://github.com/summernote/summernote" target="_blank">Project</a> · ',
50200              '<a href="https://github.com/summernote/summernote/issues" target="_blank">Issues</a>',
50201              '</p>',
50202          ].join('');
50203          this.$dialog = this.ui.dialog({
50204              title: this.lang.options.help,
50205              fade: this.options.dialogsFade,
50206              body: this.createShortcutList(),
50207              footer: body,
50208              callback: function ($node) {
50209                  $node.find('.modal-body,.note-modal-body').css({
50210                      'max-height': 300,
50211                      'overflow': 'scroll'
50212                  });
50213              }
50214          }).render().appendTo($container);
50215      };
50216      HelpDialog.prototype.destroy = function () {
50217          this.ui.hideDialog(this.$dialog);
50218          this.$dialog.remove();
50219      };
50220      HelpDialog.prototype.createShortcutList = function () {
50221          var _this = this;
50222          var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc'];
50223          return Object.keys(keyMap).map(function (key) {
50224              var command = keyMap[key];
50225              var $row = $$1('<div><div class="help-list-item"/></div>');
50226              $row.append($$1('<label><kbd>' + key + '</kdb></label>').css({
50227                  'width': 180,
50228                  'margin-right': 10
50229              })).append($$1('<span/>').html(_this.context.memo('help.' + command) || command));
50230              return $row.html();
50231          }).join('');
50232      };
50233      /**
50234       * show help dialog
50235       *
50236       * @return {Promise}
50237       */
50238      HelpDialog.prototype.showHelpDialog = function () {
50239          var _this = this;
50240          return $$1.Deferred(function (deferred) {
50241              _this.ui.onDialogShown(_this.$dialog, function () {
50242                  _this.context.triggerEvent('dialog.shown');
50243                  deferred.resolve();
50244              });
50245              _this.ui.showDialog(_this.$dialog);
50246          }).promise();
50247      };
50248      HelpDialog.prototype.show = function () {
50249          var _this = this;
50250          this.context.invoke('editor.saveRange');
50251          this.showHelpDialog().then(function () {
50252              _this.context.invoke('editor.restoreRange');
50253          });
50254      };
50255      return HelpDialog;
50256  }());
50257
50258  var AIR_MODE_POPOVER_X_OFFSET = 20;
50259  var AirPopover = /** @class */ (function () {
50260      function AirPopover(context) {
50261          var _this = this;
50262          this.context = context;
50263          this.ui = $$1.summernote.ui;
50264          this.options = context.options;
50265          this.events = {
50266              'summernote.keyup summernote.mouseup summernote.scroll': function () {
50267                  _this.update();
50268              },
50269              'summernote.disable summernote.change summernote.dialog.shown': function () {
50270                  _this.hide();
50271              },
50272              'summernote.focusout': function (we, e) {
50273                  // [workaround] Firefox doesn't support relatedTarget on focusout
50274                  //  - Ignore hide action on focus out in FF.
50275                  if (env.isFF) {
50276                      return;
50277                  }
50278                  if (!e.relatedTarget || !dom.ancestor(e.relatedTarget, func.eq(_this.$popover[0]))) {
50279                      _this.hide();
50280                  }
50281              }
50282          };
50283      }
50284      AirPopover.prototype.shouldInitialize = function () {
50285          return this.options.airMode && !lists.isEmpty(this.options.popover.air);
50286      };
50287      AirPopover.prototype.initialize = function () {
50288          this.$popover = this.ui.popover({
50289              className: 'note-air-popover'
50290          }).render().appendTo(this.options.container);
50291          var $content = this.$popover.find('.popover-content');
50292          this.context.invoke('buttons.build', $content, this.options.popover.air);
50293      };
50294      AirPopover.prototype.destroy = function () {
50295          this.$popover.remove();
50296      };
50297      AirPopover.prototype.update = function () {
50298          var styleInfo = this.context.invoke('editor.currentStyle');
50299          if (styleInfo.range && !styleInfo.range.isCollapsed()) {
50300              var rect = lists.last(styleInfo.range.getClientRects());
50301              if (rect) {
50302                  var bnd = func.rect2bnd(rect);
50303                  this.$popover.css({
50304                      display: 'block',
50305                      left: Math.max(bnd.left + bnd.width / 2, 0) - AIR_MODE_POPOVER_X_OFFSET,
50306                      top: bnd.top + bnd.height
50307                  });
50308                  this.context.invoke('buttons.updateCurrentStyle', this.$popover);
50309              }
50310          }
50311          else {
50312              this.hide();
50313          }
50314      };
50315      AirPopover.prototype.hide = function () {
50316          this.$popover.hide();
50317      };
50318      return AirPopover;
50319  }());
50320
50321  var POPOVER_DIST = 5;
50322  var HintPopover = /** @class */ (function () {
50323      function HintPopover(context) {
50324          var _this = this;
50325          this.context = context;
50326          this.ui = $$1.summernote.ui;
50327          this.$editable = context.layoutInfo.editable;
50328          this.options = context.options;
50329          this.hint = this.options.hint || [];
50330          this.direction = this.options.hintDirection || 'bottom';
50331          this.hints = Array.isArray(this.hint) ? this.hint : [this.hint];
50332          this.events = {
50333              'summernote.keyup': function (we, e) {
50334                  if (!e.isDefaultPrevented()) {
50335                      _this.handleKeyup(e);
50336                  }
50337              },
50338              'summernote.keydown': function (we, e) {
50339                  _this.handleKeydown(e);
50340              },
50341              'summernote.disable summernote.dialog.shown': function () {
50342                  _this.hide();
50343              }
50344          };
50345      }
50346      HintPopover.prototype.shouldInitialize = function () {
50347          return this.hints.length > 0;
50348      };
50349      HintPopover.prototype.initialize = function () {
50350          var _this = this;
50351          this.lastWordRange = null;
50352          this.$popover = this.ui.popover({
50353              className: 'note-hint-popover',
50354              hideArrow: true,
50355              direction: ''
50356          }).render().appendTo(this.options.container);
50357          this.$popover.hide();
50358          this.$content = this.$popover.find('.popover-content,.note-popover-content');
50359          this.$content.on('click', '.note-hint-item', function (e) {
50360              _this.$content.find('.active').removeClass('active');
50361              $$1(e.currentTarget).addClass('active');
50362              _this.replace();
50363          });
50364      };
50365      HintPopover.prototype.destroy = function () {
50366          this.$popover.remove();
50367      };
50368      HintPopover.prototype.selectItem = function ($item) {
50369          this.$content.find('.active').removeClass('active');
50370          $item.addClass('active');
50371          this.$content[0].scrollTop = $item[0].offsetTop - (this.$content.innerHe
50371ight() / 2);
50372      };
50373      HintPopover.prototype.moveDown = function () {
50374          var $current = this.$content.find('.note-hint-item.active');
50375          var $next = $current.next();
50376          if ($next.length) {
50377              this.selectItem($next);
50378          }
50379          else {
50380              var $nextGroup = $current.parent().next();
50381              if (!$nextGroup.length) {
50382                  $nextGroup = this.$content.find('.note-hint-group').first();
50383              }
50384              this.selectItem($nextGroup.find('.note-hint-item').first());
50385          }
50386      };
50387      HintPopover.prototype.moveUp = function () {
50388          var $current = this.$content.find('.note-hint-item.active');
50389          var $prev = $current.prev();
50390          if ($prev.length) {
50391              this.selectItem($prev);
50392          }
50393          else {
50394              var $prevGroup = $current.parent().prev();
50395              if (!$prevGroup.length) {
50396                  $prevGroup = this.$content.find('.note-hint-group').last();
50397              }
50398              this.selectItem($prevGroup.find('.note-hint-item').last());
50399          }
50400      };
50401      HintPopover.prototype.replace = function () {
50402          var $item = this.$content.find('.note-hint-item.active');
50403          if ($item.length) {
50404              var node = this.nodeFromItem($item);
vendor: 7,303 bytes, lines 50405-50592
50405              // XXX: consider to move codes to editor for recording redo/undo.
50406              this.lastWordRange.insertNode(node);
50407              range.createFromNode(node).collapse().select();
50408              this.lastWordRange = null;
50409              this.hide();
50410              this.context.triggerEvent('change', this.$editable.html(), this.$editable[0]);
50411              this.context.invoke('editor.focus');
50412          }
50413      };
50414      HintPopover.prototype.nodeFromItem = function ($item) {
50415          var hint = this.hints[$item.data('index')];
50416          var item = $item.data('item');
50417          var node = hint.content ? hint.content(item) : item;
50418          if (typeof node === 'string') {
50419              node = dom.createText(node);
50420          }
50421          return node;
50422      };
50423      HintPopover.prototype.createItemTemplates = function (hintIdx, items) {
50424          var hint = this.hints[hintIdx];
50425          return items.map(function (item, idx) {
50426              var $item = $$1('<div class="note-hint-item"/>');
50427              $item.append(hint.template ? hint.template(item) : item + '');
50428              $item.data({
50429                  'index': hintIdx,
50430                  'item': item
50431              });
50432              return $item;
50433          });
50434      };
50435      HintPopover.prototype.handleKeydown = function (e) {
50436          if (!this.$popover.is(':visible')) {
50437              return;
50438          }
50439          if (e.keyCode === key.code.ENTER) {
50440              e.preventDefault();
50441              this.replace();
50442          }
50443          else if (e.keyCode === key.code.UP) {
50444              e.preventDefault();
50445              this.moveUp();
50446          }
50447          else if (e.keyCode === key.code.DOWN) {
50448              e.preventDefault();
50449              this.moveDown();
50450          }
50451      };
50452      HintPopover.prototype.searchKeyword = function (index, keyword, callback) {
50453          var hint = this.hints[index];
50454          if (hint && hint.match.test(keyword) && hint.search) {
50455              var matches = hint.match.exec(keyword);
50456              hint.search(matches[1], callback);
50457          }
50458          else {
50459              callback();
50460          }
50461      };
50462      HintPopover.prototype.createGroup = function (idx, keyword) {
50463          var _this = this;
50464          var $group = $$1('<div class="note-hint-group note-hint-group-' + idx + '"/>');
50465          this.searchKeyword(idx, keyword, function (items) {
50466              items = items || [];
50467              if (items.length) {
50468                  $group.html(_this.createItemTemplates(idx, items));
50469                  _this.show();
50470              }
50471          });
50472          return $group;
50473      };
50474      HintPopover.prototype.handleKeyup = function (e) {
50475          var _this = this;
50476          if (!lists.contains([key.code.ENTER, key.code.UP, key.code.DOWN], e.keyCode)) {
50477              var wordRange = this.context.invoke('editor.getLastRange').getWordRange();
50478              var keyword_1 = wordRange.toString();
50479              if (this.hints.length && keyword_1) {
50480                  this.$content.empty();
50481                  var bnd = func.rect2bnd(lists.last(wordRange.getClientRects()));
50482                  if (bnd) {
50483                      this.$popover.hide();
50484                      this.lastWordRange = wordRange;
50485                      this.hints.forEach(function (hint, idx) {
50486                          if (hint.match.test(keyword_1)) {
50487                              _this.createGroup(idx, keyword_1).appendTo(_this.$content);
50488                          }
50489                      });
50490                      // select first .note-hint-item
50491                      this.$content.find('.note-hint-item:first').addClass('active');
50492                      // set position for popover after group is created
50493                      if (this.direction === 'top') {
50494                          this.$popover.css({
50495                              left: bnd.left,
50496                              top: bnd.top - this.$popover.outerHeight() - POPOVER_DIST
50497                          });
50498                      }
50499                      else {
50500                          this.$popover.css({
50501                              left: bnd.left,
50502                              top: bnd.top + bnd.height + POPOVER_DIST
50503                          });
50504                      }
50505                  }
50506              }
50507              else {
50508                  this.hide();
50509              }
50510          }
50511      };
50512      HintPopover.prototype.show = function () {
50513          this.$popover.show();
50514      };
50515      HintPopover.prototype.hide = function () {
50516          this.$popover.hide();
50517      };
50518      return HintPopover;
50519  }());
50520
50521  $$1.summernote = $$1.extend($$1.summernote, {
50522      version: '0.8.12',
50523      plugins: {},
50524      dom: dom,
50525      range: range,
50526      options: {
50527          langInfo: $$1.summernote.lang['en-US'],
50528          modules: {
50529              'editor': Editor,
50530              'clipboard': Clipboard,
50531              'dropzone': Dropzone,
50532              'codeview': CodeView,
50533              'statusbar': Statusbar,
50534              'fullscreen': Fullscreen,
50535              'handle': Handle,
50536              // FIXME: HintPopover must be front of autolink
50537              //  - Script error about range when Enter key is pressed on hint popover
50538              'hintPopover': HintPopover,
50539              'autoLink': AutoLink,
50540              'autoSync': AutoSync,
50541              'autoReplace': AutoReplace,
50542              'placeholder': Placeholder,
50543              'buttons': Buttons,
50544              'toolbar': Toolbar,
50545              'linkDialog': LinkDialog,
50546              'linkPopover': LinkPopover,
50547              'imageDialog': ImageDialog,
50548              'imagePopover': ImagePopover,
50549              'tablePopover': TablePopover,
50550              'videoDialog': VideoDialog,
50551              'helpDialog': HelpDialog,
50552              'airPopover': AirPopover
50553          },
50554          buttons: {},
50555          lang: 'en-US',
50556          followingToolbar: false,
50557          otherStaticBar: '',
50558          // toolbar
50559          toolbar: [
50560              ['style', ['style']],
50561              ['font', ['bold', 'underline', 'clear']],
50562              ['fontname', ['fontname']],
50563              ['color', ['color']],
50564              ['para', ['ul', 'ol', 'paragraph']],
50565              ['table', ['table']],
50566              ['insert', ['link', 'picture', 'video']],
50567              ['view', ['fullscreen', 'codeview', 'help']],
50568          ],
50569          // popover
50570          popatmouse: true,
50571          popover: {
50572              image: [
50573                  ['resize', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']],
50574                  ['float', ['floatLeft', 'floatRight', 'floatNone']],
50575                  ['remove', ['removeMedia']],
50576              ],
50577              link: [
50578                  ['link', ['linkDialogShow', 'unlink']],
50579              ],
50580              table: [
50581                  ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
50582                  ['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
50583              ],
50584              air: [
50585                  ['color', ['color']],
50586                  ['font', ['bold', 'underline', 'clear']],
50587                  ['para', ['ul', 'paragraph']],
50588                  ['table', ['table']],
50589                  ['insert', ['link', 'picture']],
50590              ]
50591          },
50592          // air mode: inline editor
50593          airMode: false,
50594          width: null,
50595          height: null,
50596          linkTargetBlank: true,
50597          focus: false,
50598          tabSize: 4,
50599          styleWithSpan: true,
50600          shortcuts: true,
50601          textareaAutoSync: true,
50602          hintDirection: 'bottom',
50603          tooltip: 'auto',
50604          container: 'body',
50605          maxTextLength: 0,
50606          blockquoteBreakingLevel: 2,
50607          spellCheck: true,
50608          styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
50609          fontNames: [
50610              'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New',
50611              'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande',
50612              'Tahoma', 'Times New Roman', 'Verdana',
50613          ],
50614          fontNamesIgnoreCheck: [],
50615          fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'],
50616          // pallete colors(n x n)
50617          colors: [
50618              ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'],
50619              ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'],
50620              ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'],
50621              ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'],
50622              ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'],
50623              ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'],
50624              ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'],
50625              ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031'],
50626          ],
50627          // http://chir.ag/projects/name-that-color/
50628          colorsName: [
50629              ['Black', 'Tundora', 'Dove Gray', 'Star Dust', 'Pale Slate', 'Gallery', 'Alabaster', 'White'],
50630              ['Red', 'Orange Peel', 'Yellow', 'Green', 'Cyan', 'Blue', 'Electric Violet', 'Magenta'],
50631              ['Azalea', 'Karry', 'Egg White', 'Zanah', 'Botticelli', 'Tropical Blue', 'Mischka', 'Twilight'],
50632              ['Tonys Pink', 'Peach Orange', 'Cream Brulee', 'Sprout', 'Casper', 'Perano', 'Cold Purple', 'Careys Pink'],
50633              ['Mandy', 'Rajah', 'Dandelion', 'Olivine', 'Gulf Stream', 'Viking', 'Blue Marguerite', 'Puce'],
50634              ['Guardsman Red', 'Fire Bush', 'Golden Dream', 'Chelsea Cucumber', 'Smalt Blue', 'Boston Blue', 'Butterfly Bush', 'Cadillac'],
50635              ['Sangria', 'Mai Tai', 'Buddha Gold', 'Forest Green', 'Eden', 'Venice Blue', 'Meteorite', 'Claret'],
50636              ['Rosewood', 'Cinnamon', 'Olive', 'Parsley', 'Tiber', 'Midnight Blue', 'Valentino', 'Loulou'],
50637          ],
50638          colorButton: {
50639              foreColor: '#000000',
50640              backColor: '#FFFF00'
50641          },
50642          lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'],
50643          tableClassName: 'table table-bordered d-table',
50644          insertTableMaxSize: {
50645              col: 10,
50646              row: 10
50647          },
50648          dialogsInBody: false,
50649          dialogsFade: false,
50650          maximumImageFileSize: null,
50651          callbacks: {
50652              onBeforeCommand: null,
50653              onBlur: null,
50654              onBlurCodeview: null,
50655              onChange: null,
50656              onChangeCodeview: null,
50657              onDialogShown: null,
50658              onEnter: null,
50659              onFocus: null,
50660              onImageLinkInsert: null,
50661              onImageUpload: null,
50662              onImageUploadError: null,
50663              onInit: null,
50664              onKeydown: null,
50665              onKeyup: null,
50666              onMousedown: null,
50667              onMouseup: null,
50668              onPaste: null,
50669              onScroll: null
50670          },
50671          codemirror: {
50672              mode: 'text/html',
50673              htmlMode: true,
50674              lineNumbers: true
50675          },
50676          codeviewFilter: false,
50677          codeviewFilterRegex: /<\/*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|ilayer|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|t(?:itle|extarea)|xml)[^>]*?>/gi,
50678          codeviewIframeFilter: true,
50679          codeviewIframeWhitelistSrc: [],
50680          codeviewIframeWhitelistSrcBase: [
50681              'www.youtube.com',
50682              'www.youtube-nocookie.com',
50683              'www.facebook.com',
50684              'vine.co',
50685              'instagram.com',
50686              'player.vimeo.com',
50687              'www.dailymotion.com',
50688              'player.youku.com',
50689              'v.qq.com',
50690          ],
50691          keyMap: {
50692              pc: {
50693                  'ENTER': 'insertParagraph',
50694                  'CTRL+Z': 'undo',
50695                  'CTRL+Y': 'redo',
50696                  'TAB': 'tab',
50697                  'SHIFT+TAB': 'untab',
50698                  'CTRL+B': 'bold',
50699                  'CTRL+I': 'italic',
50700                  'CTRL+U': 'underline',
50701                  'CTRL+SHIFT+S': 'strikethrough',
50702                  'CTRL+BACKSLASH': 'removeFormat',
50703                  'CTRL+SHIFT+L': 'justifyLeft',
50704                  'CTRL+SHIFT+E': 'justifyCenter',
50705                  'CTRL+SHIFT+R': 'justifyRight',
50706                  'CTRL+SHIFT+J': 'justifyFull',
50707                  'CTRL+SHIFT+NUM7': 'insertUnorderedList',
50708                  'CTRL+SHIFT+NUM8': 'insertOrderedList',
50709                  'CTRL+LEFTBRACKET': 'outdent',
50710                  'CTRL+RIGHTBRACKET': 'indent',
50711                  'CTRL+NUM0': 'formatPara',
50712                  'CTRL+NUM1': 'formatH1',
50713                  'CTRL+NUM2': 'formatH2',
50714                  'CTRL+NUM3': 'formatH3',
50715                  'CTRL+NUM4': 'formatH4',
50716                  'CTRL+NUM5': 'formatH5',
50717                  'CTRL+NUM6': 'formatH6',
50718                  'CTRL+ENTER': 'insertHorizontalRule',
50719                  'CTRL+K': 'linkDialog.show'
50720              },
50721              mac: {
50722                  'ENTER': 'insertParagraph',
50723                  'CMD+Z': 'undo',
50724                  'CMD+SHIFT+Z': 'redo',
50725                  'TAB': 'tab',
50726                  'SHIFT+TAB': 'untab',
50727                  'CMD+B': 'bold',
50728                  'CMD+I': 'italic',
50729                  'CMD+U': 'underline',
50730                  'CMD+SHIFT+S': 'strikethrough',
50731                  'CMD+BACKSLASH': 'removeFormat',
50732                  'CMD+SHIFT+L': 'justifyLeft',
50733                  'CMD+SHIFT+E': 'justifyCenter',
50734                  'CMD+SHIFT+R': 'justifyRight',
50735                  'CMD+SHIFT+J': 'justifyFull',
50736                  'CMD+SHIFT+NUM7': 'insertUnorderedList',
50737                  'CMD+SHIFT+NUM8': 'insertOrderedList',
50738                  'CMD+LEFTBRACKET': 'outdent',
50739                  'CMD+RIGHTBRACKET': 'indent',
50740                  'CMD+NUM0': 'formatPara',
50741                  'CMD+NUM1': 'formatH1',
50742                  'CMD+NUM2': 'formatH2',
50743                  'CMD+NUM3': 'formatH3',
50744                  'CMD+NUM4': 'formatH4',
50745                  'CMD+NUM5': 'formatH5',
50746                  'CMD+NUM6': 'formatH6',
50747                  'CMD+ENTER': 'insertHorizontalRule',
50748                  'CMD+K': 'linkDialog.show'
50749              }
50750          },
50751          icons: {
50752              'align': 'note-icon-align',
50753              'alignCenter': 'note-icon-align-center',
50754              'alignJustify': 'note-icon-align-justify',
50755              'alignLeft': 'note-icon-align-left',
50756              'alignRight': 'note-icon-align-right',
50757              'rowBelow': 'note-icon-row-below',
50758              'colBefore': 'note-icon-col-before',
50759              'colAfter': 'note-icon-col-after',
50760              'rowAbove': 'note-icon-row-above',
50761              'rowRemove': 'note-icon-row-remove',
50762              'colRemove': 'note-icon-col-remove',
50763              'indent': 'note-icon-align-indent',
50764              'outdent': 'note-icon-align-outdent',
50765              'arrowsAlt': 'note-icon-arrows-alt',
50766              'bold': 'note-icon-bold',
50767              'caret': 'note-icon-caret',
50768              'circle': 'note-icon-circle',
50769              'close': 'note-icon-close',
50770              'code': 'note-icon-code',
50771              'eraser': 'note-icon-eraser',
50772              'floatLeft': 'note-icon-float-left',
50773              'floatRight': 'note-icon-float-right',
50774              'font': 'note-icon-font',
50775              'frame': 'note-icon-frame',
50776              'italic': 'note-icon-italic',
50777              'link': 'note-icon-link',
50778              'unlink': 'note-icon-chain-broken',
50779              'magic': 'note-icon-magic',
50780              'menuCheck': 'note-icon-menu-check',
50781              'minus': 'note-icon-minus',
50782              'orderedlist': 'note-icon-orderedlist',
50783              'pencil': 'note-icon-pencil',
50784              'picture': 'note-icon-picture',
50785              'question': 'note-icon-question',
50786              'redo': 'note-icon-redo',
50787              'rollback': 'note-icon-rollback',
50788              'square': 'note-icon-square',
50789              'strikethrough': 'note-icon-strikethrough',
50790              'subscript': 'note-icon-subscript',
50791              'superscript': 'note-icon-superscript',
50792              'table': 'note-icon-table',
50793              'textHeight': 'note-icon-text-height',
50794              'trash': 'note-icon-trash',
50795              'underline': 'note-icon-underline',
50796              'undo': 'note-icon-undo',
50797              'unorderedlist': 'note-icon-unorderedlist',
50798              'video': 'note-icon-video'
50799          }
50800      }
50801  });
50802
50803  $$1.summernote = $$1.extend($$1.summernote, {
50804      ui: ui
50805  });
50806
50807}));
50808//# sourceMappingURL=summernote.js.map
50809
50810
50811
50812(function(factory){
50813    if(typeof define==='function'&&define.amd){
50814        define(['jquery'],factory);
50815    }else if(typeof module==='object'&&module.exports){
50816        module.exports=factory(require('jquery'));
50817    }else{
50818        factory(window.jQuery);
50819    }
50820}(function($){
50821    $.extend(true,$.summernote.lang,{
50822        'en-US':{
50823            imageAttributes:{
50824                tooltip:'Image Attributes',
50825                pluginImageTitle:'Image Attributes',
50826                pluginLinkTitle:'Link Attributes',
50827                title:'Title',
50828                alt:'Alt',
50829                class:'Class',
50830                style:'Style',
50831                href:'URL',
50832                target:'Target',
50833                linkClass:'Link Class',
50834                rel:'Link Rel',
50835                relBlank:'Do not use Rel Attribute',
50836                relAlternate:'Alternate: Links to an alternate version of the document',
50837                relAuthor:'Author: Links to the Author of the Document',
50838                relBookmark:'Bookmark: Permanent URL used for Bookmarking',
50839                relHelp:'Help: Links to a Help Document',
50840                relLicense:'License: Links to copyright information for the document',
50841                relNext:'Next: The next document in a selection',
50842                relNofollow:'NoFollow: Links to an unendorsed document, like a paid link, also stops Search Engines following this link',
50843                relNoreferrer:'NoReferrer: Specifies that the browser should not send a HTTP Header',
50844                relPrefetch:'PreFetch: Specifies that the target document should be cached',
50845                relPrev:'Prev: The previous document in a selection',
50846                relSearch:'Search: Links to a search tool for the document',
50847                relTag:'Tag: A tag (Keyword) for the current documentNext'
50848            }
50849        }
50850    });
50851    $.extend($.summernote.options,{
50852        imageAttributes:{
50853            icon:'<i class="fa fa-edit"></i>', // This Icon is from the LibreICONS class Extras and SVG Icons for Summernote.
50854            removeEmpty:true
50855        }
50856    })
50857    $.extend($.summernote.plugins,{
50858        'imageAttributes':function(context){
50859            var self=this;
50860            var ui=$.summernote.ui;
50861            var $note=context.layoutInfo.note;
50862            var $editor=context.layoutInfo.editor;
50863            var $editable=context.layoutInfo.editable;
50864            var options=context.options;
50865            var lang=options.langInfo;
50866            context.memo('button.imageAttributes',function(){
50867                var button=ui.button({
50868                    contents:options.imageAttributes.icon,
50869                    tooltip:lang.imageAttributes.tooltip,
50870                    click:function(e){
50871                        context.invoke('imageAttributes.show');
50872                    }
50873                });
50874                return button.render();
50875            });
50876            this.initialize=function(){
50877                var $container=options.dialogsInBody?$(document.body):$editor;
50878                var body='<h5 class="d-none">'+lang.imageAttributes.pluginImageTitle+'</h5>'+
50879                    '<div class="form-group d-none">'+
50880                    '<label class="control-label col-xs-2">'+lang.imageAttributes.title+'</label>'+
50881                    '<div class="input-group col-xs-10">'+
50882                    '<input type="text" class="note-image-attributes-title form-control">'+
50883                    '</div>'+
50884                    '</div>'+
50885                    '<div class="form-group d-none">'+
50886                    '<label class="control-label col-xs-2">'+lang.imageAttributes.alt+'</label>'+
50887                    '<div class="input-group col-xs-10">'+
50888                    '<input type="text" class="note-image-attributes-alt form-control">'+
50889                    '</div>'+
50890                    '</div>'+
50891                    '<div class="form-group d-none">'+
50892                    '<label class="control-label col-xs-2">'+lang.imageAttributes.class+'</label>'+
50893                    '<div class="input-group col-xs-10">'+
50894                    '<input type="text" class="note-image-attributes-class form-control">'+
50895                    '<div class="input-group-btn">'+
50896                    '<select class="note-image-attributes-class-select btn btn-default" onchange="$(\'.note-image-attributes-class\').val($(\'.note-image-attributes-class\').val()+\' \'+$(this).val());">'+
50897                    '<option value="">Select Class</option>'+
50898                    '<option value="img-responsive">Responsive</option>'+
50899                    '<option value="img-rounded">Rounded</option>'+
50900                    '<option value="img-circle">Circle</option>'+
50901                    '<option value="img-thumbnail">Thumbnail</option>'+
50902                    '</select>'+
50903                    '</div>'+
50904                    '</div>'+
50905                    '</div>'+
50906                    '<div class="form-group d-none">'+
50907                    '<label class="control-label col-xs-2">'+lang.imageAttributes.style + '</label>'+
50908                    '<div class="input-group col-xs-10">'+
50909                    '<input type="text" class="note-image-attributes-style form-control">'+
50910                    '</div>'+
50911                    '</div>'+
50912                    '<h5 class="d-none">'+lang.imageAttributes.pluginLinkTitle+'</h5>'+
50913                    '<div class="form-group">'+
50914                    '<label class="control-label col-xs-2">'+lang.imageAttributes.href+'</label>'+
50915                    '<div class="input-group col-xs-10">'+
50916                    '<input type="text" class="note-image-attributes-href form-control" name="href">'+
50917                    '</div>'+
50918                    '</div>'+
50919                    '<div class="form-group">'+
50920                    '<label class="control-label col-xs-2">'+lang.imageAttributes.target+'</label>'+
50921                    '<div class="input-group col-xs-10">'+
50922                    '<select class="note-image-attributes-target form-control" name="target">'+
50923                    '<option value="_self">Self</option>'+
50924                    '<option value="_blank">Blank</option>'+
50925                    '<option value="_top">Top</option>'+
50926                    '<option value="_parent">Parent</option>'+
50927                    '</select>'+
50928                    '</div>'+
50929                    '</div>'+
50930                    '<div class="form-group d-none">'+
50931                    '<label class="control-label col-xs-2">'+lang.imageAttributes.linkClass+'</label>'+
50932                    '<div class="input-group col-xs-10">'+
50933                    '<input type="text" class="note-image-attributes-link-class form-control" name="linkClass">'+
50934                    '</div>'+
50935                    '</div>'+
50936                    '<div class="form-group d-none">'+
50937                    '<label class="control-label col-xs-2">'+lang.imageAttributes.rel+'</label>'+
50938                    '<div class="input-group col-xs-10">'+
50939                    '<select class="note-image-attributes-link-rel form-control" name="linkRel">'+
50940                    '<option value="">'+lang.imageAttributes.relBlank+'</option>'+
50941                    '<option value="alternate">'+lang.imageAttributes.relAlternate+'</option>'+
50942                    '<option value="author">'+lang.imageAttributes.relAuthor+'</option>'+
50943                    '<option value="bookmark">'+lang.imageAttributes.relBookmark+'</option>'+
50944                    '<option value="help">'+lang.imageAttributes.relHelp+'</option>'+
50945                    '<option value="license">'+lang.imageAttributes.relLicense+'</option>'+
50946                    '<option value="next">'+lang.imageAttributes.relNext+'</option>'+
50947                    '<option value="nofollow">'+lang.imageAttributes.relNofollow+'</option>'+
50948                    '<option value="noreferrer">'+lang.imageAttributes.relNoreferrer+'</option>'+
50949                    '<option value="prefetch">'+lang.imageAttributes.relPrefetch+'</option>'+
50950                    '<option value="prev">'+lang.imageAttributes.relPrev+'</option>'+
50951                    '<option value="search">'+lang.imageAttributes.relSearch+'</option>'+
50952                    '<option value="tag">'+lang.imageAttributes.relTag+'</option>'+
50953                    '</select>'+
50954                    '</div>'+
50955                    '</div>';
50956                this.$dialog=ui.dialog({
50957                    title:'Image Attributes',
50958                    body:body,
50959                    footer:'<button href="#" class="btn btn-primary note-image-attributes-btn">OK</button>'
50960                }).render().appendTo($container);
50961            };
50962            this.destroy=function(){
50963                ui.hideDialog(this.$dialog);
50964                this.$dialog.remove();
50965            };
50966            this.bindEnterKey=function($input,$btn){
50967                $input.on('keypress',function(event){
50968                    if(event.keyCode===13){
50969                        $btn.trigger('click');
50970                    }
50971                });
50972            };
50973            this.show=function(){
50974                var $img=$($editable.data('target'));
50975                var imgInfo={
50976                    imgDom:$img,
50977                    title:$img.attr('title'),
50978                    alt:$img.attr('alt'),
50979                    class:$img.attr('class'),
50980                    style:$img.attr('style'),
50981                    imgLink:$($img.context).parent().is("a")?$($img.context).parent():null
50982                };
50983                this.showLinkDialog(imgInfo)
50984                    .then(function(imgInfo){
50985                        ui.hideDialog(self.$dialog);
50986                        var $img=imgInfo.imgDom;
50987                        if(options.imageAttributes.removeEmpty){
50988                            if(imgInfo.alt){
50989                                $img.attr('alt',imgInfo.alt);
50990                            }else{
50991                                $img.removeAttr('alt');
50992                            }
50993                            if(imgInfo.title){
50994                                $img.attr('title',imgInfo.title);
50995                            }else{
50996                                $img.removeAttr('title');
50997                            }
50998                            if(imgInfo.class){
50999                                $img.attr('class',imgInfo.class);
51000                            }else{
51001                                $img.removeAttr('class');
51002                            }
51003                            if(imgInfo.style){
51004                                $img.attr('style',imgInfo.style);
51005                            }else{
51006                                $img.removeAttr('style');
51007                            }
51008                        }else{
51009                            $img.attr('alt',imgInfo.alt);
51010                            $img.attr('title',imgInfo.title);
51011                            $img.attr('class',imgInfo.class);
51012                            $img.attr('style',imgInfo.style);
51013                        }
51014                        if($img.parent().is("a")){
51015                            $img.unwrap();
51016                        }
51017                        var hrefRegex=new RegExp(/(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/gi);
51018                        if(imgInfo.href.match(hrefRegex)){
51019                            var lnktxt='<a';
51020                            if(imgInfo.linkClass){
51021                                lnktxt+=' class="'+imgInfo.linkClass+'"';
51022                            }
51023                            lnktxt+=' href="'+imgInfo.href+'"';
51024                            lnktxt+=' target="'+imgInfo.target+'"';
51025                            if(imgInfo.linkRel){
51026                                lnktxt+=' ref="'+imgInfo.linkRel+'"';
51027                            }
51028                            lnktxt+='></a>';
51029                            $img.wrap(lnktxt);
51030                        }
51031                        $note.val(context.invoke('code'));
51032                        $note.change();
51033                    });
51034            };
51035            this.showLinkDialog=function(imgInfo){
51036                return $.Deferred(function(deferred){
51037                    var $imageTitle=self.$dialog.find('.note-image-attributes-title'),
51038                        $imageAlt=self.$dialog.find('.note-image-attributes-alt'),
51039                        $imageClass=self.$dialog.find('.note-image-attributes-class'),
51040                        $imageStyle=self.$dialog.find('.note-image-attributes-style'),
51041                        $linkHref=self.$dialog.find('.note-image-attributes-href'),
51042                        $linkTarget=self.$dialog.find('.note-image-attributes-target'),
51043                        $linkClass=self.$dialog.find('.note-image-attributes-link-class'),
51044                        $linkRel=self.$dialog.find('.note-image-attributes-link-rel'),
51045                        $editBtn=self.$dialog.find('.note-image-attributes-btn');
51046                    if(imgInfo.imgLink){
51047                        $linkHref.val(imgInfo.imgLink.attr('href'));
51048                        $linkClass.val(imgInfo.imgLink.attr('class'));
51049                        $linkTarget.find('option').each(function(){
51050                            if($(this).val()==imgInfo.imgLink.attr('target')){
51051                                $(this).attr('selected','selected');
51052                            }
51053                        });
51054                        $linkRel.find('option').each(function(){
51055                            if($(this).val()==imgInfo.imgLink.attr('rel')){
51056                                $(this).attr('selected','selected');
51057                            }
51058                        });
51059                    }
51060                    ui.onDialogShown(self.$dialog,function(){
51061                        context.triggerEvent('dialog.shown');
51062                        $editBtn.click(function(e){
51063                            e.preventDefault();
51064                            deferred.resolve({
51065                                imgDom:imgInfo.imgDom,
51066                                title:$imageTitle.val(),
51067                                alt:$imageAlt.val(),
51068                                class:$imageClass.val(),
51069                                style:$imageStyle.val(),
51070                                href:$linkHref.val(),
51071                                target:$linkTarget.val(),
51072                                linkClass:$linkClass.val(),
51073                                linkRel:$linkRel.val()
51074                            });
51075                        });
51076                        $imageTitle.val(imgInfo.title).focus;
51077                        $imageAlt.val(imgInfo.alt);
51078                        $imageClass.val(imgInfo.class);
51079                        $imageStyle.val(imgInfo.style);
51080                        self.bindEnterKey(
51081                            $editBtn
51082                        );
51083                    });
51084                    ui.onDialogHidden(self.$dialog,function(){
51085                        $editBtn.off('click');
51086                        if(deferred.state()==='pending'){
51087                            deferred.reject();
51088                        }
51089                    });
51090                    ui.showDialog(self.$dialog);
51091                });
51092            };
51093        }
51094    });
51095}));
51096
51097
51098
51099
51100
51101// Released under MIT license
51102// Copyright (c) 2009-2010 Dominic Baggott
51103// Copyright (c) 2009-2010 Ash Berlin
51104// Copyright (c) 2011 Christoph Dorn <[email protected]> (http://www.christophdorn.com)
51105
51106/*jshint browser:true, devel:true */
51107
51108(function( expose ) {
51109
51110/**
51111 *  class Markdown
51112 *
51113 *  Markdown processing in Javascript done right. We have very particular views
51114 *  on what constitutes 'right' which include:
51115 *
51116 *  - produces well-formed HTML (this means that em and strong nesting is
51117 *    important)
51118 *
51119 *  - has an intermediate representation to allow processing of parsed data (We
51120 *    in fact have two, both as [JsonML]: a markdown tree and an HTML tree).
51121 *
51122 *  - is easily extensible to add new dialects without having to rewrite the
51123 *    entire parsing mechanics
51124 *
51125 *  - has a good test suite
51126 *
51127 *  This implementation fulfills all of these (except that the test suite could
51128 *  do with expanding to automatically run all the fixtures from other Markdown
51129 *  implementations.)
51130 *
51131 *  ##### Intermediate Representation
51132 *
51133 *  *TODO* Talk about this :) Its JsonML, but document the node names we use.
51134 *
51135 *  [JsonML]: http://jsonml.org/ "JSON Markup Language"
51136 **/
51137var Markdown = expose.Markdown = function(dialect) {
51138  switch (typeof dialect) {
51139    case "undefined":
51140      this.dialect = Markdown.dialects.Gruber;
51141      break;
51142    case "object":
51143      this.dialect = dialect;
51144      break;
51145    default:
51146      if ( dialect in Markdown.dialects ) {
51147        this.dialect = Markdown.dialects[dialect];
51148      }
51149      else {
51150        throw new Error("Unknown Markdown dialect '" + String(dialect) + "'");
51151      }
51152      break;
51153  }
51154  this.em_state = [];
51155  this.strong_state = [];
51156  this.debug_indent = "";
51157};
51158
51159/**
51160 *  parse( markdown, [dialect] ) -> JsonML
51161 *  - markdown (String): markdown string to parse
51162 *  - dialect (String | Dialect): the dialect to use, defaults to gruber
51163 *
51164 *  Parse `markdown` and return a markdown document as a Markdown.JsonML tree.
51165 **/
51166expose.parse = function( source, dialect ) {
51167  // dialect will default if undefined
51168  var md = new Markdown( dialect );
51169  return md.toTree( source );
51170};
51171
51172/**
51173 *  toHTML( markdown, [dialect]  ) -> String
51174 *  toHTML( md_tree ) -> String
51175 *  - markdown (String): markdown string to parse
51176 *  - md_tree (Markdown.JsonML): parsed markdown tree
51177 *
51178 *  Take markdown (either as a string or as a JsonML tree) and run it through
51179 *  [[toHTMLTree]] then turn it into a well-formated HTML fragment.
51180 **/
51181expose.toHTML = function toHTML( source , dialect , options ) {
51182  var input = expose.toHTMLTree( source , dialect , options );
51183
51184  return expose.renderJsonML( input );
51185};
51186
51187/**
51188 *  toHTMLTree( markdown, [dialect] ) -> JsonML
51189 *  toHTMLTree( md_tree ) -> JsonML
51190 *  - markdown (String): markdown string to parse
51191 *  - dialect (String | Dialect): the dialect to use, defaults to gruber
51192 *  - md_tree (Markdown.JsonML): parsed markdown tree
51193 *
51194 *  Turn markdown into HTML, represented as a JsonML tree. If a string is given
51195 *  to this function, it is first parsed into a markdown tree by calling
51196 *  [[parse]].
51197 **/
51198expose.toHTMLTree = function toHTMLTree( input, dialect , options ) {
51199  // convert string input to an MD tree
51200  if ( typeof input ==="string" ) input = this.parse( input, dialect );
51201
51202  // Now convert the MD tree to an HTML tree
51203
51204  // remove references from the tree
51205  var attrs = extract_attr( input ),
51206      refs = {};
51207
51208  if ( attrs && attrs.references ) {
51209    refs = attrs.references;
51210  }
51211
51212  var html = convert_tree_to_html( input, refs , options );
51213  merge_text_nodes( html );
51214  return html;
51215};
51216
51217// For Spidermonkey based engines
51218function mk_block_toSource() {
51219  return "Markdown.mk_block( " +
51220          uneval(this.toString()) +
51221          ", " +
51222          uneval(this.trailing) +
51223          ", " +
51224          uneval(this.lineNumber) +
51225          " )";
51226}
51227
51228// node
51229function mk_block_inspect() {
51230  var util = require("util");
51231  return "Markdown.mk_block( " +
51232          util.inspect(this.toString()) +
51233          ", " +
51234          util.inspect(this.trailing) +
51235          ", " +
51236          util.inspect(this.lineNumber) +
51237          " )";
51238
51239}
51240
51241var mk_block = Markdown.mk_block = function(block, trail, line) {
51242  // Be helpful for default case in tests.
51243  if ( arguments.length == 1 ) trail = "\n\n";
51244
51245  var s = new String(block);
51246  s.trailing = trail;
51247  // To make it clear its not just a string
51248  s.inspect = mk_block_inspect;
51249  s.toSource = mk_block_toSource;
51250
51251  if ( line != undefined )
51252    s.lineNumber = line;
51253
51254  return s;
51255};
51256
51257function count_lines( str ) {
51258  var n = 0, i = -1;
51259  while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) n++;
51260  return n;
51261}
51262
51263// Internal - split source into rough blocks
51264Markdown.prototype.split_blocks = function splitBlocks( input, startLine ) {
51265  input = input.replace(/(\r\n|\n|\r)/g, "\n");
51266  // [\s\S] matches _anything_ (newline or space)
51267  // [^] is equivalent but doesn't work in IEs.
51268  var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g,
51269      blocks = [],
51270      m;
51271
51272  var line_no = 1;
51273
51274  if ( ( m = /^(\s*\n)/.exec(input) ) != null ) {
51275    // skip (but count) leading blank lines
51276    line_no += count_lines( m[0] );
51277    re.lastIndex = m[0].length;
51278  }
51279
51280  while ( ( m = re.exec(input) ) !== null ) {
51281    if (m[2] == "\n#") {
51282      m[2] = "\n";
51283      re.lastIndex--;
51284    }
51285    blocks.push( mk_block( m[1], m[2], line_no ) );
51286    line_no += count_lines( m[0] );
51287  }
51288
51289  return blocks;
51290};
51291
51292/**
51293 *  Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]
51294 *  - block (String): the block to process
51295 *  - next (Array): the following blocks
51296 *
51297 * Process `block` and return an array of JsonML nodes representing `block`.
51298 *
51299 * It does this by asking each block level function in the dialect to process
51300 * the block until one can. Succesful handling is indicated by returning an
51301 * array (with zero or more JsonML nodes), failure by a false value.
51302 *
51303 * Blocks handlers are responsible for calling [[Markdown#processInline]]
51304 * themselves as appropriate.
51305 *
51306 * If the blocks were split incorrectly or adjacent blocks need collapsing you
51307 * can adjust `next` in place using shift/splice etc.
51308 *
51309 * If any of this default behaviour is not right for the dialect, you can
51310 * define a `__call__` method on the dialect that will get invoked to handle
51311 * the block processing.
51312 */
51313Markdown.prototype.processBlock = function processBlock( block, next ) {
51314  var cbs = this.dialect.block,
51315      ord = cbs.__order__;
51316
51317  if ( "__call__" in cbs ) {
51318    return cbs.__call__.call(this, block, next);
51319  }
51320
51321  for ( var i = 0; i < ord.length; i++ ) {
51322    //D:this.debug( "Testing", ord[i] );
51323    var res = cbs[ ord[i] ].call( this, block, next );
51324    if ( res ) {
51325      //D:this.debug("  matched");
51326      if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) )
51327        this.debug(ord[i], "didn't return a proper array");
51328      //D:this.debug( "" );
51329      return res;
51330    }
51331  }
51332
51333  // Uhoh! no match! Should we throw an error?
51334  return [];
51335};
51336
51337Markdown.prototype.processInline = function processInline( block ) {
51338  return this.dialect.inline.__call__.call( this, String( block ) );
51339};
51340
51341/**
51342 *  Markdown#toTree( source ) -> JsonML
51343 *  - source (String): markdown source to parse
51344 *
51345 *  Parse `source` into a JsonML tree representing the markdown document.
51346 **/
51347// custom_tree means set this.tree to `custom_tree` and restore old value on return
51348Markdown.prototype.toTree = function toTree( source, custom_root ) {
51349  var blocks = source instanceof Array ? source : this.split_blocks( source );
51350
51351  // Make tree a member variable so its easier to mess with in extensions
51352  var old_tree = this.tree;
51353  try {
51354    this.tree = custom_root || this.tree || [ "markdown" ];
51355
51356    blocks:
51357    while ( blocks.length ) {
51358      var b = this.processBlock( blocks.shift(), blocks );
51359
51360      // Reference blocks and the like won't return any content
51361      if ( !b.length ) continue blocks;
51362
51363      this.tree.push.apply( this.tree, b );
51364    }
51365    return this.tree;
51366  }
51367  finally {
51368    if ( custom_root ) {
51369      this.tree = old_tree;
51370    }
51371  }
51372};
51373
51374// Noop by default
51375Markdown.prototype.debug = function () {
51376  var args = Array.prototype.slice.call( arguments);
51377  args.unshift(this.debug_indent);
51378  if ( typeof print !== "undefined" )
51379      print.apply( print, args );
51380  if ( typeof console !== "undefined" && typeof console.log !== "undefined" )
51381      console.log.apply( null, args );
51382}
51383
51384Markdown.prototype.loop_re_over_block = function( re, block, cb ) {
51385  // Dont use /g regexps with this
51386  var m,
51387      b = block.valueOf();
51388
51389  while ( b.length && (m = re.exec(b) ) != null ) {
51390    b = b.substr( m[0].length );
51391    cb.call(this, m);
51392  }
51393  return b;
51394};
51395
51396/**
51397 * Markdown.dialects
51398 *
51399 * Namespace of built-in dialects.
51400 **/
51401Markdown.dialects = {};
51402
51403/**
51404 * Markdown.dialects.Gruber
51405 *
51406 * The default dialect that follows the rules set out by John Gruber's
51407 * markdown.pl as closely as possible. Well actually we follow the behaviour of
51408 * that script which in some places is not exactly what the syntax web page
51409 * says.
51410 **/
51411Markdown.dialects.Gruber = {
51412  block: {
51413    atxHeader: function atxHeader( block, next ) {
51414      var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );
51415
51416      if ( !m ) return undefined;
51417
51418      var header = [ "header", { level: m[ 1 ].length } ];
51419      Array.prototype.push.apply(header, this.processInline(m[ 2 ]));
51420
51421      if ( m[0].length < block.length )
51422        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
51423
51424      return [ header ];
51425    },
51426
51427    setextHeader: function setextHeader( block, next ) {
51428      var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ );
51429
51430      if ( !m ) return undefined;
51431
51432      var level = ( m[ 2 ] === "=" ) ? 1 : 2;
51433      var header = [ "header", { level : level }, m[ 1 ] ];
51434
51435      if ( m[0].length < block.length )
51436        next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
51437
51438      return [ header ];
51439    },
51440
51441    code: function code( block, next ) {
51442      // |    Foo
51443      // |bar
51444      // should be a code block followed by a paragraph. Fun
51445      //
51446      // There might also be adjacent code block to merge.
51447
51448      var ret = [],
51449          re = /^(?: {0,3}\t| {4})(.*)\n?/,
51450          lines;
51451
51452      // 4 spaces + content
51453      if ( !block.match( re ) ) return undefined;
51454
51455      block_search:
51456      do {
51457        // Now pull out the rest of the lines
51458        var b = this.loop_re_over_block(
51459                  re, block.valueOf(), function( m ) { ret.push( m[1] ); } );
51460
51461        if ( b.length ) {
51462          // Case alluded to in first comment. push it back on as a new block
51463          next.unshift( mk_block(b, block.trailing) );
51464          break block_search;
51465        }
51466        else if ( next.length ) {
51467          // Check the next block - it might be code too
51468          if ( !next[0].match( re ) ) break block_search;
51469
51470          // Pull how how many blanks lines follow - minus two to account for .join
51471          ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) );
51472
51473          block = next.shift();
51474        }
51475        else {
51476          break block_search;
51477        }
51478      } while ( true );
51479
51480      return [ [ "code_block", ret.join("\n") ] ];
51481    },
51482
51483    horizRule: function horizRule( block, next ) {
51484      // this needs to find any hr in the block to handle abutting blocks
51485      var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ );
51486
51487      if ( !m ) {
51488        return undefined;
51489      }
51490
51491      var jsonml = [ [ "hr" ] ];
51492
51493      // if there's a leading abutting block, process it
51494      if ( m[ 1 ] ) {
51495        jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) );
51496      }
51497
51498      // if there's a trailing abutting block, stick it into next
51499      if ( m[ 3 ] ) {
51500        next.unshift( mk_block( m[ 3 ] ) );
51501      }
51502
51503      return jsonml;
51504    },
51505
51506    // There are two types of lists. Tight and loose. Tight lists have no whitespace
51507    // between the items (and result in text just in the <li>) and loose lists,
51508    // which have an empty line between list items, resulting in (one or more)
51509    // paragraphs inside the <li>.
51510    //
51511    // There are all sorts weird edge cases about the original markdown.pl's
51512    // handling of lists:
51513    //
51514    // * Nested lists are supposed to be indented by four chars per level. But
51515    //   if they aren't, you can get a nested list by indenting by less than
51516    //   four so long as the indent doesn't match an indent of an existing list
51517    //   item in the 'nest stack'.
51518    //
51519    // * The type of the list (bullet or number) is controlled just by the
51520    //    first item at the indent. Subsequent changes are ignored unless they
51521    //    are for nested lists
51522    //
51523    lists: (function( ) {
51524      // Use a closure to hide a few variables.
51525      var any_list = "[*+-]|\\d+\\.",
51526          bullet_list = /[*+-]/,
51527          number_list = /\d+\./,
51528          // Capture leading indent as it matters for determining nested lists.
51529          is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ),
51530          indent_re = "(?: {0,3}\\t| {4})";
51531
51532      // TODO: Cache this regexp for certain depths.
51533      // Create a regexp suitable for matching an li for a given stack depth
51534      function regex_for_depth( depth ) {
51535
51536        return new RegExp(
51537          // m[1] = indent, m[2] = list_type
51538          "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" +
51539          // m[3] = cont
51540          "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})"
51541        );
51542      }
51543      function expand_tab( input ) {
51544        return input.replace( / {0,3}\t/g, "    " );
51545      }
51546
51547      // Add inline content `inline` to `li`. inline comes from processInline
51548      // so is an array of content
51549      function add(li, loose, inline, nl) {
51550        if ( loose ) {
51551          li.push( [ "para" ].concat(inline) );
51552          return;
51553        }
51554        // Hmmm, should this be any block level element or just paras?
51555        var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == "para"
51556                   ? li[li.length -1]
51557                   : li;
51558
51559        // If there is already some content in this list, add the new line in
51560        if ( nl && li.length > 1 ) inline.unshift(nl);
51561
51562        for ( var i = 0; i < inline.length; i++ ) {
51563          var what = inline[i],
51564              is_str = typeof what == "string";
51565          if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) {
51566            add_to[ add_to.length-1 ] += what;
51567          }
51568          else {
51569            add_to.push( what );
51570          }
51571        }
51572      }
51573
51574      // contained means have an indent greater than the current one. On
51575      // *every* line in the block
51576      function get_contained_blocks( depth, blocks ) {
51577
51578        var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ),
51579            replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"),
51580            ret = [];
51581
51582        while ( blocks.length > 0 ) {
51583          if ( re.exec( blocks[0] ) ) {
51584            var b = blocks.shift(),
51585                // Now remove that indent
51586                x = b.replace( replace, "");
51587
51588            ret.push( mk_block( x, b.trailing, b.lineNumber ) );
51589          }
51590          else {
51591            break;
51592          }
51593        }
51594        return ret;
51595      }
51596
51597      // passed to stack.forEach to turn list items up the stack into paras
51598      function paragraphify(s, i, stack) {
51599        var list = s.list;
51600        var last_li = list[list.length-1];
51601
51602        if ( last_li[1] instanceof Array && last_li[1][0] == "para" ) {
51603          return;
51604        }
51605        if ( i + 1 == stack.length ) {
51606          // Last stack frame
51607          // Keep the same array, but replace the contents
51608          last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) );
51609        }
51610        else {
51611          var sublist = last_li.pop();
51612          last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist );
51613        }
51614      }
51615
51616      // The matcher function
51617      return function( block, next ) {
51618        var m = block.match( is_list_re );
51619        if ( !m ) return undefined;
51620
51621        function make_list( m ) {
51622          var list = bullet_list.exec( m[2] )
51623                   ? ["bulletlist"]
51624                   : ["numberlist"];
51625
51626          stack.push( { list: list, indent: m[1] } );
51627          return list;
51628        }
51629
51630
51631        var stack = [], // Stack of lists for nesting.
51632            list = make_list( m ),
51633            last_li,
51634            loose = false,
51635            ret = [ stack[0].list ],
51636            i;
51637
51638        // Loop to search over block looking for inner block elements and loose lists
51639        loose_search:
51640        while ( true ) {
51641          // Split into lines preserving new lines at end of line
51642          var lines = block.split( /(?=\n)/ );
51643
51644          // We have to grab all lines for a li and call processInline on them
51645          // once as there are some inline things that can span lines.
51646          var li_accumulate = "";
51647
51648          // Loop over the lines in this block looking for tight lists.
51649          tight_search:
51650          for ( var line_no = 0; line_no < lines.length; line_no++ ) {
51651            var nl = "",
51652                l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });
51653
51654            // TODO: really should cache this
51655            var line_re = regex_for_depth( stack.length );
51656
51657            m = l.match( line_re );
51658            //print( "line:", uneval(l), "\nline match:", uneval(m) );
51659
51660            // We have a list item
51661            if ( m[1] !== undefined ) {
51662              // Process the previous list item, if any
51663              if ( li_accumulate.length ) {
51664                add( last_li, loose, this.processInline( li_accumulate ), nl );
51665                // Loose mode will have been dealt with. Reset it
51666                loose = false;
51667                li_accumulate = "";
51668              }
51669
51670              m[1] = expand_tab( m[1] );
51671              var wanted_depth = Math.floor(m[1].length/4)+1;
51672              //print( "want:", wanted_depth, "stack:", stack.length);
51673              if ( wanted_depth > stack.length ) {
51674                // Deep enough for a nested list outright
51675                //print ( "new nested list" );
51676                list = make_list( m );
51677                last_li.push( list );
51678                last_li = list[1] = [ "listitem" ];
51679              }
51680              else {
51681                // We aren't deep enough to be strictly a new level. This is
51682                // where Md.pl goes nuts. If the indent matches a level in the
51683                // stack, put it there, else put it one deeper then the
51684                // wanted_depth deserves.
51685                var found = false;
51686                for ( i = 0; i < stack.length; i++ ) {
51687                  if ( stack[ i ].indent != m[1] ) continue;
51688                  list = stack[ i ].list;
51689                  stack.splice( i+1, stack.length - (i+1) );
51690                  found = true;
51691                  break;
51692                }
51693
51694                if (!found) {
51695                  //print("not found. l:", uneval(l));
51696                  wanted_depth++;
51697                  if ( wanted_depth <= stack.length ) {
51698                    stack.splice(wanted_depth, stack.length - wanted_depth);
51699                    //print("Desired depth now", wanted_depth, "stack:", stack.length);
51700                    list = stack[wanted_depth-1].list;
51701                    //print("list:", uneval(list) );
51702                  }
51703                  else {
51704                    //print ("made new stack for messy indent");
51705                    list = make_list(m);
51706                    last_li.push(list);
51707                  }
51708                }
51709
51710                //print( uneval(list), "last", list === stack[stack.length-1].list );
51711                last_li = [ "listitem" ];
51712                list.push(last_li);
51713              } // end depth of shenegains
51714              nl = "";
51715            }
51716
51717            // Add content
51718            if ( l.length > m[0].length ) {
51719              li_accumulate += nl + l.substr( m[0].length );
51720            }
51721          } // tight_search
51722
51723          if ( li_accumulate.length ) {
51724            add( last_li, loose, this.processInline( li_accumulate ), nl );
51725            // Loose mode will have been dealt with. Reset it
51726            loose = false;
51727            li_accumulate = "";
51728          }
51729
51730          // Look at the next block - we might have a loose list. Or an extra
51731          // paragraph for the current li
51732          var contained = get_contained_blocks( stack.length, next );
51733
51734          // Deal with code blocks or properly nested lists
51735          if ( contained.length > 0 ) {
51736            // Make sure all listitems up the stack are paragraphs
51737            forEach( stack, paragraphify, this);
51738
51739            last_li.push.apply( last_li, this.toTree( contained, [] ) );
51740          }
51741
51742          var next_block = next[0] && next[0].valueOf() || "";
51743
51744          if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {
51745            block = next.shift();
51746
51747            // Check for an HR following a list: features/lists/hr_abutting
51748            var hr = this.dialect.block.horizRule( block, next );
51749
51750            if ( hr ) {
51751              ret.push.apply(ret, hr);
51752              break;
51753            }
51754
51755            // Make sure all listitems up the stack are paragraphs
51756            forEach( stack, paragraphify, this);
51757
51758            loose = true;
51759            continue loose_search;
51760          }
51761          break;
51762        } // loose_search
51763
51764        return ret;
51765      };
51766    })(),
51767
51768    blockquote: function blockquote( block, next ) {
51769      if ( !block.match( /^>/m ) )
51770        return undefined;
51771
51772      var jsonml = [];
51773
51774      // separate out the leading abutting block, if any. I.e. in this case:
51775      //
51776      //  a
51777      //  > b
51778      //
51779      if ( block[ 0 ] != ">" ) {
51780        var lines = block.split( /\n/ ),
51781            prev = [],
51782            line_no = block.lineNumber;
51783
51784        // keep shifting lines until you find a crotchet
51785        while ( lines.length && lines[ 0 ][ 0 ] != ">" ) {
51786            prev.push( lines.shift() );
51787            line_no++;
51788        }
51789
51790        var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber );
51791        jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) );
51792        // reassemble new block of just block quotes!
51793        block = mk_block( lines.join( "\n" ), block.trailing, line_no );
51794      }
51795
51796
51797      // if the next block is also a blockquote merge it in
51798      while ( next.length && next[ 0 ][ 0 ] == ">" ) {
51799        var b = next.shift();
51800        block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber );
51801      }
51802
51803      // Strip off the leading "> " and re-process as a block.
51804      var input = block.replace( /^> ?/gm, "" ),
51805          old_tree = this.tree,
51806          processedBlock = this.toTree( input, [ "blockquote" ] ),
51807          attr = extract_attr( processedBlock );
51808
51809      // If any link references were found get rid of them
51810      if ( attr && attr.references ) {
51811        delete attr.references;
51812        // And then remove the attribute object if it's empty
51813        if ( isEmpty( attr ) ) {
51814          processedBlock.splice( 1, 1 );
51815        }
51816      }
51817
51818      jsonml.push( processedBlock );
51819      return jsonml;
51820    },
51821
51822    referenceDefn: function referenceDefn( block, next) {
51823      var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;
51824      // interesting matches are [ , ref_id, url, , title, title ]
51825
51826      if ( !block.match(re) )
51827        return undefined;
51828
51829      // make an attribute node if it doesn't exist
51830      if ( !extract_attr( this.tree ) ) {
51831        this.tree.splice( 1, 0, {} );
51832      }
51833
51834      var attrs = extract_attr( this.tree );
51835
51836      // make a references hash if it doesn't exist
51837      if ( attrs.references === undefined ) {
51838        attrs.references = {};
51839      }
51840
51841      var b = this.loop_re_over_block(re, block, function( m ) {
51842
51843        if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
51844          m[2] = m[2].substring( 1, m[2].length - 1 );
51845
51846        var ref = attrs.references[ m[1].toLowerCase() ] = {
51847          href: m[2]
51848        };
51849
51850        if ( m[4] !== undefined )
51851          ref.title = m[4];
51852        else if ( m[5] !== undefined )
51853          ref.title = m[5];
51854
51855      } );
51856
51857      if ( b.length )
51858        next.unshift( mk_block( b, block.trailing ) );
51859
51860      return [];
51861    },
51862
51863    para: function para( block, next ) {
51864      // everything's a para!
51865      return [ ["para"].concat( this.processInline( block ) ) ];
51866    }
51867  }
51868};
51869
51870Markdown.dialects.Gruber.inline = {
51871
51872    __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
51873      var m,
51874          res,
51875          lastIndex = 0;
51876
51877      patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
51878      var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
51879
51880      m = re.exec( text );
51881      if (!m) {
51882        // Just boring text
51883        return [ text.length, text ];
51884      }
51885      else if ( m[1] ) {
51886        // Some un-interesting text matched. Return that first
51887        return [ m[1].length, m[1] ];
51888      }
51889
51890      var res;
51891      if ( m[2] in this.dialect.inline ) {
51892        res = this.dialect.inline[ m[2] ].call(
51893                  this,
51894                  text.substr( m.index ), m, previous_nodes || [] );
51895      }
51896      // Default for now to make dev easier. just slurp special and output it.
51897      res = res || [ m[2].length, m[2] ];
51898      return res;
51899    },
51900
51901    __call__: function inline( text, patterns ) {
51902
51903      var out = [],
51904          res;
51905
51906      function add(x) {
51907        //D:self.debug("  adding output", uneval(x));
51908        if ( typeof x == "string" && typeof out[out.length-1] == "string" )
51909          out[ out.length-1 ] += x;
51910        else
51911          out.push(x);
51912      }
51913
51914      while ( text.length > 0 ) {
51915        res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );
51916        text = text.substr( res.shift() );
51917        forEach(res, add )
51918      }
51919
51920      return out;
51921    },
51922
51923    // These characters are intersting elsewhere, so have rules for them so that
51924    // chunks of plain text blocks don't include them
51925    "]": function () {},
51926    "}": function () {},
51927
51928    __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/,
51929
51930    "\\": function escaped( text ) {
51931      // [ length of input processed, node/children to add... ]
51932      // Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
51933      if ( this.dialect.inline.__escape__.exec( text ) )
51934        return [ 2, text.charAt( 1 ) ];
51935      else
51936        // Not an esacpe
51937        return [ 1, "\\" ];
51938    },
51939
51940    "![": function image( text ) {
51941
51942      // Unlike images, alt text is plain text only. no other elements are
51943      // allowed in there
51944
51945      // ![Alt text](/path/to/img.jpg "Optional title")
51946      //      1          2            3       4         <--- captures
51947      var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
51948
51949      if ( m ) {
51950        if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
51951          m[2] = m[2].substring( 1, m[2].length - 1 );
51952
51953        m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
51954
51955        var attrs = { alt: m[1], href: m[2] || "" };
51956        if ( m[4] !== undefined)
51957          attrs.title = m[4];
51958
51959        return [ m[0].length, [ "img", attrs ] ];
51960      }
51961
51962      // ![Alt text][id]
51963      m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ );
51964
51965      if ( m ) {
51966        // We can't check if the reference is known here as it likely wont be
51967        // found till after. Check it in md tree->hmtl tree conversion
51968        return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
51969      }
51970
51971      // Just consume the '!['
51972      return [ 2, "![" ];
51973    },
51974
51975    "[": function link( text ) {
51976
51977      var orig = String(text);
51978      // Inline content is possible inside `link text`
51979      var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), "]" );
51980
51981      // No closing ']' found. Just consume the [
51982      if ( !res ) return [ 1, "[" ];
51983
51984      var consumed = 1 + res[ 0 ],
51985          children = res[ 1 ],
51986          link,
51987          attrs;
51988
51989      // At this point the first [...] has been parsed. See what follows to find
51990      // out which kind of link we are (reference or direct url)
51991      text = text.substr( consumed );
51992
51993      // [link text](/path/to/img.jpg "Optional title")
51994      //                 1            2       3         <--- captures
51995      // This will capture up to the last paren in the block. We then pull
51996      // back based on if there a matching ones in the url
51997      //    ([here](/url/(test))
51998      // The parens have to be balanced
51999      var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
52000      if ( m ) {
52001        var url = m[1];
52002        consumed += m[0].length;
52003
52004        if ( url && url[0] == "<" && url[url.length-1] == ">" )
52005          url = url.substring( 1, url.length - 1 );
52006
52007        // If there is a title we don't have to worry about parens in the url
52008        if ( !m[3] ) {
52009          var open_parens = 1; // One open that isn't in the capture
52010          for ( var len = 0; len < url.length; len++ ) {
52011            switch ( url[len] ) {
52012            case "(":
52013              open_parens++;
52014              break;
52015            case ")":
52016              if ( --open_parens == 0) {
52017                consumed -= url.length - len;
52018                url = url.substring(0, len);
52019              }
52020              break;
52021            }
52022          }
52023        }
52024
52025        // Process escapes only
52026        url = this.dialect.inline.__call__.call( this, url, /\\/ )[0];
52027
52028        attrs = { href: url || "" };
52029        if ( m[3] !== undefined)
52030          attrs.title = m[3];
52031
52032        link = [ "link", attrs ].concat( children );
52033        return [ consumed, link ];
52034      }
52035
52036      // [Alt text][id]
52037      // [Alt text] [id]
52038      m = text.match( /^\s*\[(.*?)\]/ );
52039
52040      if ( m ) {
52041
52042        consumed += m[ 0 ].length;
52043
52044        // [links][] uses links as its reference
52045        attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(),  original: orig.substr( 0, consumed ) };
52046
52047        link = [ "link_ref", attrs ].concat( children );
52048
52049        // We can't check if the reference is known here as it likely wont be
52050        // found till after. Check it in md tree->hmtl tree conversion.
52051        // Store the original so that conversion can revert if the ref isn't found.
52052        return [ consumed, link ];
52053      }
52054
52055      // [id]
52056      // Only if id is plain (no formatting.)
52057      if ( children.length == 1 && typeof children[0] == "string" ) {
52058
52059        attrs = { ref: children[0].toLowerCase(),  original: orig.substr( 0, consumed ) };
52060        link = [ "link_ref", attrs, children[0] ];
52061        return [ consumed, link ];
52062      }
52063
52064      // Just consume the "["
52065      return [ 1, "[" ];
52066    },
52067
52068
52069    "<": function autoLink( text ) {
52070      var m;
52071
52072      if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) != null ) {
52073        if ( m[3] ) {
52074          return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ];
52075
52076        }
52077        else if ( m[2] == "mailto" ) {
52078          return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ];
52079        }
52080        else
52081          return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ];
52082      }
52083
52084      return [ 1, "<" ];
52085    },
52086
52087    "`": function inlineCode( text ) {
52088      // Inline code block. as many backticks as you like to start it
52089      // Always skip over the opening ticks.
52090      var m = text.match( /(`+)(([\s\S]*?)\1)/ );
52091
52092      if ( m && m[2] )
52093        return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ];
52094      else {
52095        // TODO: No matching end code found - warn!
52096        return [ 1, "`" ];
52097      }
52098    },
52099
52100    "  \n": function lineBreak( text ) {
52101      return [ 3, [ "linebreak" ] ];
52102    }
52103
52104};
52105
52106// Meta Helper/generator method for em and strong handling
52107function strong_em( tag, md ) {
52108
52109  var state_slot = tag + "_state",
52110      other_slot = tag == "strong" ? "em_state" : "strong_state";
52111
52112  function CloseTag(len) {
52113    this.len_after = len;
52114    this.name = "close_" + md;
52115  }
52116
52117  return function ( text, orig_match ) {
52118
52119    if ( this[state_slot][0] == md ) {
52120      // Most recent em is of this type
52121      //D:this.debug("closing", md);
52122      this[state_slot].shift();
52123
52124      // "Consume" everything to go back to the recrusion in the else-block below
52125      return[ text.length, new CloseTag(text.length-md.length) ];
52126    }
52127    else {
52128      // Store a clone of the em/strong states
52129      var other = this[other_slot].slice(),
52130          state = this[state_slot].slice();
52131
52132      this[state_slot].unshift(md);
52133
52134      //D:this.debug_indent += "  ";
52135
52136      // Recurse
52137      var res = this.processInline( text.substr( md.length ) );
52138      //D:this.debug_indent = this.debug_indent.substr(2);
52139
52140      var last = res[res.length - 1];
52141
52142      //D:this.debug("processInline from", tag + ": ", uneval( res ) );
52143
52144      var check = this[state_slot].shift();
52145      if ( last instanceof CloseTag ) {
52146        res.pop();
52147        // We matched! Huzzah.
52148        var consumed = text.length - last.len_after;
52149        return [ consumed, [ tag ].concat(res) ];
52150      }
52151      else {
52152        // Restore the state of the other kind. We might have mistakenly closed it.
52153        this[other_slot] = other;
52154        this[state_slot] = state;
52155
52156        // We can't reuse the processed result as it could have wrong parsing contexts in it.
52157        return [ md.length, md ];
52158      }
52159    }
52160  }; // End returned function
52161}
52162
52163Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
52164Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
52165Markdown.dialects.Gruber.inline["*"]  = strong_em("em", "*");
52166Markdown.dialects.Gruber.inline["_"]  = strong_em("em", "_");
52167
52168
52169// Build default order from insertion order.
52170Markdown.buildBlockOrder = function(d) {
52171  var ord = [];
52172  for ( var i in d ) {
52173    if ( i == "__order__" || i == "__call__" ) continue;
52174    ord.push( i );
52175  }
52176  d.__order__ = ord;
52177};
52178
52179// Build patterns for inline matcher
52180Markdown.buildInlinePatterns = function(d) {
52181  var patterns = [];
52182
52183  for ( var i in d ) {
52184    // __foo__ is reserved and not a pattern
52185    if ( i.match( /^__.*__$/) ) continue;
52186    var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" )
52187             .replace( /\n/, "\\n" );
52188    patterns.push( i.length == 1 ? l : "(?:" + l + ")" );
52189  }
52190
52191  patterns = patterns.join("|");
52192  d.__patterns__ = patterns;
52193  //print("patterns:", uneval( patterns ) );
52194
52195  var fn = d.__call__;
52196  d.__call__ = function(text, pattern) {
52197    if ( pattern != undefined ) {
52198      return fn.call(this, text, pattern);
52199    }
52200    else
52201    {
52202      return fn.call(this, text, patterns);
52203    }
52204  };
52205};
52206
52207Markdown.DialectHelpers = {};
52208Markdown.DialectHelpers.inline_until_char = function( text, want ) {
52209  var consumed = 0,
52210      nodes = [];
52211
52212  while ( true ) {
52213    if ( text.charAt( consumed ) == want ) {
52214      // Found the character we were looking for
52215      consumed++;
52216      return [ consumed, nodes ];
52217    }
52218
52219    if ( consumed >= text.length ) {
52220      // No closing char found. Abort.
52221      return null;
52222    }
52223
52224    var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );
52225    consumed += res[ 0 ];
52226    // Add any returned nodes.
52227    nodes.push.apply( nodes, res.slice( 1 ) );
52228  }
52229}
52230
52231// Helper function to make sub-classing a dialect easier
52232Markdown.subclassDialect = function( d ) {
52233  function Block() {}
52234  Block.prototype = d.block;
52235  function Inline() {}
52236  Inline.prototype = d.inline;
52237
52238  return { block: new Block(), inline: new Inline() };
52239};
52240
52241Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );
52242Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );
52243
52244Markdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber );
52245
52246Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {
52247  var meta = split_meta_hash( meta_string ),
52248      attr = {};
52249
52250  for ( var i = 0; i < meta.length; ++i ) {
52251    // id: #foo
52252    if ( /^#/.test( meta[ i ] ) ) {
52253      attr.id = meta[ i ].substring( 1 );
52254    }
52255    // class: .foo
52256    else if ( /^\./.test( meta[ i ] ) ) {
52257      // if class already exists, append the new one
52258      if ( attr["class"] ) {
52259        attr["class"] = attr["class"] + meta[ i ].replace( /./, " " );
52260      }
52261      else {
52262        attr["class"] = meta[ i ].substring( 1 );
52263      }
52264    }
52265    // attribute: foo=bar
52266    else if ( /\=/.test( meta[ i ] ) ) {
52267      var s = meta[ i ].split( /\=/ );
52268      attr[ s[ 0 ] ] = s[ 1 ];
52269    }
52270  }
52271
52272  return attr;
52273}
52274
52275function split_meta_hash( meta_string ) {
52276  var meta = meta_string.split( "" ),
52277      parts = [ "" ],
52278      in_quotes = false;
52279
52280  while ( meta.length ) {
52281    var letter = meta.shift();
52282    switch ( letter ) {
52283      case " " :
52284        // if we're in a quoted section, keep it
52285        if ( in_quotes ) {
52286          parts[ parts.length - 1 ] += letter;
52287        }
52288        // otherwise make a new part
52289        else {
52290          parts.push( "" );
52291        }
52292        break;
52293      case "'" :
52294      case '"' :
52295        // reverse the quotes and move straight on
52296        in_quotes = !in_quotes;
52297        break;
52298      case "\\" :
52299        // shift off the next letter to be used straight away.
52300        // it was escaped so we'll keep it whatever it is
52301        letter = meta.shift();
52302      default :
52303        parts[ parts.length - 1 ] += letter;
52304        break;
52305    }
52306  }
52307
52308  return parts;
52309}
52310
52311Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {
52312  // we're only interested in the first block
52313  if ( block.lineNumber > 1 ) return undefined;
52314
52315  // document_meta blocks consist of one or more lines of `Key: Value\n`
52316  if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) return undefined;
52317
52318  // make an attribute node if it doesn't exist
52319  if ( !extract_attr( this.tree ) ) {
52320    this.tree.splice( 1, 0, {} );
52321  }
52322
52323  var pairs = block.split( /\n/ );
52324  for ( p in pairs ) {
52325    var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ),
52326        key = m[ 1 ].toLowerCase(),
52327        value = m[ 2 ];
52328
52329    this.tree[ 1 ][ key ] = value;
52330  }
52331
52332  // document_meta produces no content!
52333  return [];
52334};
52335
52336Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {
52337  // check if the last line of the block is an meta hash
52338  var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ );
52339  if ( !m ) return undefined;
52340
52341  // process the meta hash
52342  var attr = this.dialect.processMetaHash( m[ 2 ] );
52343
52344  var hash;
52345
52346  // if we matched ^ then we need to apply meta to the previous block
52347  if ( m[ 1 ] === "" ) {
52348    var node = this.tree[ this.tree.length - 1 ];
52349    hash = extract_attr( node );
52350
52351    // if the node is a string (rather than JsonML), bail
52352    if ( typeof node === "string" ) return undefined;
52353
52354    // create the attribute hash if it doesn't exist
52355    if ( !hash ) {
52356      hash = {};
52357      node.splice( 1, 0, hash );
52358    }
52359
52360    // add the attributes in
52361    for ( a in attr ) {
52362      hash[ a ] = attr[ a ];
52363    }
52364
52365    // return nothing so the meta hash is removed
52366    return [];
52367  }
52368
52369  // pull the meta hash off the block and process what's left
52370  var b = block.replace( /\n.*$/, "" ),
52371      result = this.processBlock( b, [] );
52372
52373  // get or make the attributes hash
52374  hash = extract_attr( result[ 0 ] );
52375  if ( !hash ) {
52376    hash = {};
52377    result[ 0 ].splice( 1, 0, hash );
52378  }
52379
52380  // attach the attributes to the block
52381  for ( a in attr ) {
52382    hash[ a ] = attr[ a ];
52383  }
52384
52385  return result;
52386};
52387
52388Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {
52389  // one or more terms followed by one or more definitions, in a single block
52390  var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
52391      list = [ "dl" ],
52392      i, m;
52393
52394  // see if we're dealing with a tight or loose block
52395  if ( ( m = block.match( tight ) ) ) {
52396    // pull subsequent tight DL blocks out of `next`
52397    var blocks = [ block ];
52398    while ( next.length && tight.exec( next[ 0 ] ) ) {
52399      blocks.push( next.shift() );
52400    }
52401
52402    for ( var b = 0; b < blocks.length; ++b ) {
52403      var m = blocks[ b ].match( tight ),
52404          terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ),
52405          defns = m[ 2 ].split( /\n:\s+/ );
52406
52407      // print( uneval( m ) );
52408
52409      for ( i = 0; i < terms.length; ++i ) {
52410        list.push( [ "dt", terms[ i ] ] );
52411      }
52412
52413      for ( i = 0; i < defns.length; ++i ) {
52414        // run inline processing over the definition
52415        list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );
52416      }
52417    }
52418  }
52419  else {
52420    return undefined;
52421  }
52422
52423  return [ list ];
52424};
52425
52426// splits on unescaped instances of @ch. If @ch is not a character the result
52427// can be unpredictable
52428
52429Markdown.dialects.Maruku.block.table = function table (block, next) {
52430
52431    var _split_on_unescaped = function(s, ch) {
52432        ch = ch || '\\s';
52433        if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; }
52434        var res = [ ],
52435            r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
52436            m;
52437        while(m = s.match(r)) {
52438            res.push(m[1]);
52439            s = m[2];
52440        }
52441        res.push(s);
52442        return res;
52443    }
52444
52445    var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
52446        // find at least an unescaped pipe in each line
52447        no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
52448        i, m;
52449    if (m = block.match(leading_pipe)) {
52450        // remove leading pipes in contents
52451        // (header and horizontal rule already have the leading pipe left out)
52452        m[3] = m[3].replace(/^\s*\|/gm, '');
52453    } else if (! ( m = block.match(no_leading_pipe))) {
52454        return undefined;
52455    }
52456
52457    var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
52458
52459    // remove trailing pipes, then split on pipes
52460    // (no escaped pipes are allowed in horizontal rule)
52461    m[2] = m[2].replace(/\|\s*$/, '').split('|');
52462
52463    // process alignment
52464    var html_attrs = [ ];
52465    forEach (m[2], function (s) {
52466        if (s.match(/^\s*-+:\s*$/))       html_attrs.push({align: "right"});
52467        else if (s.match(/^\s*:-+\s*$/))  html_attrs.push({align: "left"});
52468        else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"});
52469        else                              html_attrs.push({});
52470    });
52471
52472    // now for the header, avoid escaped pipes
52473    m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
52474    for (i = 0; i < m[1].length; i++) {
52475        table[1][1].push(['th', html_attrs[i] || {}].concat(
52476            this.processInline(m[1][i].trim())));
52477    }
52478
52479    // now for body contents
52480    forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
52481        var html_row = ['tr'];
52482        row = _split_on_unescaped(row, '|');
52483        for (i = 0; i < row.length; i++) {
52484            html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
52485        }
52486        table[2].push(html_row);
52487    }, this);
52488
52489    return [table];
52490}
52491
52492Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
52493  if ( !out.length ) {
52494    return [ 2, "{:" ];
52495  }
52496
52497  // get the preceeding element
52498  var before = out[ out.length - 1 ];
52499
52500  if ( typeof before === "string" ) {
52501    return [ 2, "{:" ];
52502  }
52503
52504  // match a meta hash
52505  var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ );
52506
52507  // no match, false alarm
52508  if ( !m ) {
52509    return [ 2, "{:" ];
52510  }
52511
52512  // attach the attributes to the preceeding element
52513  var meta = this.dialect.processMetaHash( m[ 1 ] ),
52514      attr = extract_attr( before );
52515
52516  if ( !attr ) {
52517    attr = {};
52518    before.splice( 1, 0, attr );
52519  }
52520
52521  for ( var k in meta ) {
52522    attr[ k ] = meta[ k ];
52523  }
52524
52525  // cut out the string and replace it with nothing
52526  return [ m[ 0 ].length, "" ];
52527};
52528
52529Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
52530
52531Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
52532Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
52533
52534var isArray = Array.isArray || function(obj) {
52535  return Object.prototype.toString.call(obj) == "[object Array]";
52536};
52537
52538var forEach;
52539// Don't mess with Array.prototype. Its not friendly
52540if ( Array.prototype.forEach ) {
52541  forEach = function( arr, cb, thisp ) {
52542    return arr.forEach( cb, thisp );
52543  };
52544}
52545else {
52546  forEach = function(arr, cb, thisp) {
52547    for (var i = 0; i < arr.length; i++) {
52548      cb.call(thisp || arr, arr[i], i, arr);
52549    }
52550  }
52551}
52552
52553var isEmpty = function( obj ) {
52554  for ( var key in obj ) {
52555    if ( hasOwnProperty.call( obj, key ) ) {
52556      return false;
52557    }
52558  }
52559
52560  return true;
52561}
52562
52563function extract_attr( jsonml ) {
52564  return isArray(jsonml)
52565      && jsonml.length > 1
52566      && typeof jsonml[ 1 ] === "object"
52567      && !( isArray(jsonml[ 1 ]) )
52568      ? jsonml[ 1 ]
52569      : undefined;
52570}
52571
52572
52573
52574/**
52575 *  renderJsonML( jsonml[, options] ) -> String
52576 *  - jsonml (Array): JsonML array to render to XML
52577 *  - options (Object): options
52578 *
52579 *  Converts the given JsonML into well-formed XML.
52580 *
52581 *  The options currently understood are:
52582 *
52583 *  - root (Boolean): wether or not the root node should be included in the
52584 *    output, or just its children. The default `false` is to not include the
52585 *    root itself.
52586 */
52587expose.renderJsonML = function( jsonml, options ) {
52588  options = options || {};
52589  // include the root element in the rendered output?
52590  options.root = options.root || false;
52591
52592  var content = [];
52593
52594  if ( options.root ) {
52595    content.push( render_tree( jsonml ) );
52596  }
52597  else {
52598    jsonml.shift(); // get rid of the tag
52599    if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
52600      jsonml.shift(); // get rid of the attributes
52601    }
52602
52603    while ( jsonml.length ) {
52604      content.push( render_tree( jsonml.shift() ) );
52605    }
52606  }
52607
52608  return content.join( "\n\n" );
52609};
52610
52611function escapeHTML( text ) {
52612  return text.replace( /&/g, "&amp;" )
52613             .replace( /</g, "&lt;" )
52614             .replace( />/g, "&gt;" )
52615             .replace( /"/g, "&quot;" )
52616             .replace( /'/g, "&#39;" );
52617}
52618
52619function render_tree( jsonml ) {
52620  // basic case
52621  if ( typeof jsonml === "string" ) {
52622    return escapeHTML( jsonml );
52623  }
52624
52625  var tag = jsonml.shift(),
52626      attributes = {},
52627      content = [];
52628
52629  if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
52630    attributes = jsonml.shift();
52631  }
52632
52633  while ( jsonml.length ) {
52634    content.push( render_tree( jsonml.shift() ) );
52635  }
52636
52637  var tag_attrs = "";
52638  for ( var a in attributes ) {
52639    tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"';
52640  }
52641
52642  // be careful about adding whitespace here for inline elements
52643  if ( tag == "img" || tag == "br" || tag == "hr" ) {
52644    return "<"+ tag + tag_attrs + "/>";
52645  }
52646  else {
52647    return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">";
52648  }
52649}
52650
52651function convert_tree_to_html( tree, references, options ) {
52652  var i;
52653  options = options || {};
52654
52655  // shallow clone
52656  var jsonml = tree.slice( 0 );
52657
52658  if ( typeof options.preprocessTreeNode === "function" ) {
52659      jsonml = options.preprocessTreeNode(jsonml, references);
52660  }
52661
52662  // Clone attributes if they exist
52663  var attrs = extract_attr( jsonml );
52664  if ( attrs ) {
52665    jsonml[ 1 ] = {};
52666    for ( i in attrs ) {
52667      jsonml[ 1 ][ i ] = attrs[ i ];
52668    }
52669    attrs = jsonml[ 1 ];
52670  }
52671
52672  // basic case
52673  if ( typeof jsonml === "string" ) {
52674    return jsonml;
52675  }
52676
52677  // convert this node
52678  switch ( jsonml[ 0 ] ) {
52679    case "header":
52680      jsonml[ 0 ] = "h" + jsonml[ 1 ].level;
52681      delete jsonml[ 1 ].level;
52682      break;
52683    case "bulletlist":
52684      jsonml[ 0 ] = "ul";
52685      break;
52686    case "numberlist":
52687      jsonml[ 0 ] = "ol";
52688      break;
52689    case "listitem":
52690      jsonml[ 0 ] = "li";
52691      break;
52692    case "para":
52693      jsonml[ 0 ] = "p";
52694      break;
52695    case "markdown":
52696      jsonml[ 0 ] = "html";
52697      if ( attrs ) delete attrs.references;
52698      break;
52699    case "code_block":
52700      jsonml[ 0 ] = "pre";
52701      i = attrs ? 2 : 1;
52702      var code = [ "code" ];
52703      code.push.apply( code, jsonml.splice( i, jsonml.length - i ) );
52704      jsonml[ i ] = code;
52705      break;
52706    case "inlinecode":
52707      jsonml[ 0 ] = "code";
52708      break;
52709    case "img":
52710      jsonml[ 1 ].src = jsonml[ 1 ].href;
52711      delete jsonml[ 1 ].href;
52712      break;
52713    case "linebreak":
52714      jsonml[ 0 ] = "br";
52715    break;
52716    case "link":
52717      jsonml[ 0 ] = "a";
52718      break;
52719    case "link_ref":
52720      jsonml[ 0 ] = "a";
52721
52722      // grab this ref and clean up the attribute node
52723      var ref = references[ attrs.ref ];
52724
52725      // if the reference exists, make the link
52726      if ( ref ) {
52727        delete attrs.ref;
52728
52729        // add in the href and title, if present
52730        attrs.href = ref.href;
52731        if ( ref.title ) {
52732          attrs.title = ref.title;
52733        }
52734
52735        // get rid of the unneeded original text
52736        delete attrs.original;
52737      }
52738      // the reference doesn't exist, so revert to plain text
52739      else {
52740        return attrs.original;
52741      }
52742      break;
52743    case "img_ref":
52744      jsonml[ 0 ] = "img";
52745
52746      // grab this ref and clean up the attribute node
52747      var ref = references[ attrs.ref ];
52748
52749      // if the reference exists, make the link
52750      if ( ref ) {
52751        delete attrs.ref;
52752
52753        // add in the href and title, if present
52754        attrs.src = ref.href;
52755        if ( ref.title ) {
52756          attrs.title = ref.title;
52757        }
52758
52759        // get rid of the unneeded original text
52760        delete attrs.original;
52761      }
52762      // the reference doesn't exist, so revert to plain text
52763      else {
52764        return attrs.original;
52765      }
52766      break;
52767  }
52768
52769  // convert all the children
52770  i = 1;
52771
52772  // deal with the attribute node, if it exists
52773  if ( attrs ) {
52774    // if there are keys, skip over it
52775    for ( var key in jsonml[ 1 ] ) {
52776        i = 2;
52777        break;
52778    }
52779    // if there aren't, remove it
52780    if ( i === 1 ) {
52781      jsonml.splice( i, 1 );
52782    }
52783  }
52784
52785  for ( ; i < jsonml.length; ++i ) {
52786    jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options );
52787  }
52788
52789  return jsonml;
52790}
52791
52792
52793// merges adjacent text nodes into a single node
52794function merge_text_nodes( jsonml ) {
52795  // skip the tag name and attribute hash
52796  var i = extract_attr( jsonml ) ? 2 : 1;
52797
52798  while ( i < jsonml.length ) {
52799    // if it's a string check the next item too
52800    if ( typeof jsonml[ i ] === "string" ) {
52801      if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) {
52802        // merge the second string into the first and remove it
52803        jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];
52804      }
52805      else {
52806        ++i;
52807      }
52808    }
52809    // if it's not a string recurse
52810    else {
52811      merge_text_nodes( jsonml[ i ] );
52812      ++i;
52813    }
52814  }
52815}
52816
52817} )( (function() {
52818  if ( typeof exports === "undefined" ) {
52819    window.markdown = {};
52820    return window.markdown;
52821  }
52822  else {
52823    return exports;
52824  }
52825} )() );
52826
52827/* ===================================================
52828 * bootstrap-markdown.js v2.10.0
52829 * http://github.com/toopay/bootstrap-markdown
52830 * ===================================================
52831 * Copyright 2013-2016 Taufan Aditya
52832 *
52833 * Licensed under the Apache License, Version 2.0 (the "License");
52834 * you may not use this file except in compliance with the License.
52835 * You may obtain a copy of the License at
52836 *
52837 * http://www.apache.org/licenses/LICENSE-2.0
52838 *
52839 * Unless required by applicable law or agreed to in writing, software
52840 * distributed under the License is distributed on an "AS IS" BASIS,
52841 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52842 * See the License for the specific language governing permissions and
52843 * limitations under the License.
52844 * ========================================================== */
52845
52846(function(factory){
52847    if (typeof define === "function" && define.amd) {
52848        //RequireJS
52849        define(["jquery"], factory);
52850    } else if (typeof exports === 'object') {
52851        //Backbone.js
52852        factory(require('jquery'));
52853    } else {
52854        //Jquery plugin
52855        factory(jQuery);
52856    }
52857}(function($){
52858  "use strict"; // jshint ;_;
52859
52860  /* MARKDOWN CLASS DEFINITION
52861   * ========================== */
52862
52863  var Markdown = function (element, options) {
52864    // @TODO : remove this BC on next major release
52865    // @see : https://github.com/toopay/bootstrap-markdown/issues/109
52866    var opts = ['autofocus', 'savable', 'hideable', 'width', 
52867      'height', 'resize', 'iconlibrary', 'language', 
52868      'footer', 'fullscreen', 'hiddenButtons', 'disabledButtons'];
52869    $.each(opts,function(_, opt){
52870      if (typeof $(element).data(opt) !== 'undefined') {
52871        options = typeof options == 'object' ? options : {}
52872        options[opt] = $(element).data(opt)
52873      }
52874    });
52875    // End BC
52876
52877    // Class Properties
52878    this.$ns           = 'bootstrap-markdown';
52879    this.$element      = $(element);
52880    this.$editable     = {el:null, type:null,attrKeys:[], attrValues:[], content:null};
52881    this.$options      = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data('options'));
52882    this.$oldContent   = null;
52883    this.$isPreview    = false;
52884    this.$isFullscreen = false;
52885    this.$editor       = null;
52886    this.$textarea     = null;
52887    this.$handler      = [];
52888    this.$callback     = [];
52889    this.$nextTab      = [];
52890
52891    this.showEditor();
52892  };
52893
52894  Markdown.prototype = {
52895
52896    constructor: Markdown
52897
52898  , __alterButtons: function(name,alter) {
52899      var handler = this.$handler, isAll = (name == 'all'),that = this;
52900
52901      $.each(handler,function(k,v) {
52902        var halt = true;
52903        if (isAll) {
52904          halt = false;
52905        } else {
52906          halt = v.indexOf(name) < 0;
52907        }
52908
52909        if (halt === false) {
52910          alter(that.$editor.find('button[data-handler="'+v+'"]'));
52911        }
52912      });
52913    }
52914
52915  , __buildButtons: function(buttonsArray, container) {
52916      var i,
52917          ns = this.$ns,
52918          handler = this.$handler,
52919          callback = this.$callback;
52920
52921      for (i=0;i<buttonsArray.length;i++) {
52922        // Build each group container
52923        var y, btnGroups = buttonsArray[i];
52924        for (y=0;y<btnGroups.length;y++) {
52925          // Build each button group
52926          var z,
52927              buttons = btnGroups[y].data,
52928              btnGroupContainer = $('<div/>', {
52929                                    'class': 'btn-group'
52930                                  });
52931
52932          for (z=0;z<buttons.length;z++) {
52933            var button = buttons[z],
52934                buttonContainer, buttonIconContainer,
52935                buttonHandler = ns+'-'+button.name,
52936                buttonIcon = this.__getIcon(button.icon),
52937                btnText = button.btnText ? button.btnText : '',
52938                btnClass = button.btnClass ? button.btnClass : 'btn',
52939                tabIndex = button.tabIndex ? button.tabIndex : '-1',
52940                hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '',
52941                hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' ('+hotkey+')' : '';
52942
52943            // Construct the button object
52944            buttonContainer = $('<button></button>');
52945            buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-default btn-sm').addClass(btnClass);
52946            if(btnClass.match(/btn\-(primary|success|info|warning|danger|link)/)){
52947                buttonContainer.removeClass('btn-default');
52948            }
52949            buttonContainer.attr({
52950                'type': 'button',
52951                'title': this.__localize(button.title) + hotkeyCaption,
52952                'tabindex': tabIndex,
52953                'data-provider': ns,
52954                'data-handler': buttonHandler,
52955                'data-hotkey': hotkey
52956            });
52957            if (button.toggle === true){
52958              buttonContainer.attr('data-toggle', 'button');
52959            }
52960            buttonIconContainer = $('<span/>');
52961            buttonIconContainer.addClass(buttonIcon);
52962            buttonIconContainer.prependTo(buttonContainer);
52963
52964            // Attach the button object
52965            btnGroupContainer.append(buttonContainer);
52966
52967            // Register handler and callback
52968            handler.push(buttonHandler);
52969            callback.push(button.callback);
52970          }
52971
52972          // Attach the button group into container dom
52973          container.append(btnGroupContainer);
52974        }
52975      }
52976
52977      return container;
52978    }
52979  , __setListener: function() {
52980      // Set size and resizable Properties
52981      var hasRows = typeof this.$textarea.attr('rows') !== 'undefined',
52982          maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5',
52983          rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows;
52984
52985      this.$textarea.attr('rows',rowsVal);
52986      if (this.$options.resize) {
52987        this.$textarea.css('resize',this.$options.resize);
52988      }
52989
52990      this.$textarea.on({
52991          'focus' : $.proxy(this.focus, this),
52992          'keyup' : $.proxy(this.keyup, this),
52993          'change' : $.proxy(this.change, this),
52994          'select' : $.proxy(this.select, this)
52995      });
52996
52997      if (this.eventSupported('keydown')) {
52998        this.$textarea.on('keydown', $.proxy(this.keydown, this));
52999      }
53000
53001      if (this.eventSupported('keypress')) {
53002        this.$textarea.on('keypress', $.proxy(this.keypress, this))
53003      }
53004
53005      // Re-attach markdown data
53006      this.$textarea.data('markdown',this);
53007    }
53008
53009  , __handle: function(e) {
53010      var target = $(e.currentTarget),
53011          handler = this.$handler,
53012          callback = this.$callback,
53013          handlerName = target.attr('data-handler'),
53014          callbackIndex = handler.indexOf(handlerName),
53015          callbackHandler = callback[callbackIndex];
53016
53017      // Trigger the focusin
53018      $(e.currentTarget).focus();
53019
53020      callbackHandler(this);
53021
53022      // Trigger onChange for each button handle
53023      this.change(this);
53024
53025      // Unless it was the save handler,
53026      // focusin the textarea
53027      if (handlerName.indexOf('cmdSave') < 0) {
53028        this.$textarea.focus();
53029      }
53030
53031      e.preventDefault();
53032    }
53033
53034  , __localize: function(string) {
53035      var messages = $.fn.markdown.messages,
53036          language = this.$options.language;
53037      if (
53038        typeof messages !== 'undefined' &&
53039        typeof messages[language] !== 'undefined' &&
53040        typeof messages[language][string] !== 'undefined'
53041      ) {
53042        return messages[language][string];
53043      }
53044      return string;
53045    }
53046
53047  , __getIcon: function(src) {
53048    return typeof src == 'object' ? src[this.$options.iconlibrary] : src;
53049  }
53050
53051  , setFullscreen: function(mode) {
53052    var $editor = this.$editor,
53053        $textarea = this.$textarea;
53054
53055    if (mode === true) {
53056      $editor.addClass('md-fullscreen-mode');
53057      $('body').addClass('md-nooverflow');
53058      this.$options.onFullscreen(this);
53059    } else {
53060      $editor.removeClass('md-fullscreen-mode');
53061      $('body').removeClass('md-nooverflow');
53062
53063      if (this.$isPreview == true) this.hidePreview().showPreview()
53064    }
53065
53066    this.$isFullscreen = mode;
53067    $textarea.focus();
53068  }
53069
53070  , showEditor: function() {
53071      var instance = this,
53072          textarea,
53073          ns = this.$ns,
53074          container = this.$element,
53075          originalHeigth = container.css('height'),
53076          originalWidth = container.css('width'),
53077          editable = this.$editable,
53078          handler = this.$handler,
53079          callback = this.$callback,
53080          options = this.$options,
53081          editor = $( '<div/>', {
53082                      'class': 'md-editor',
53083                      click: function() {
53084                        instance.focus();
53085                      }
53086                    });
53087
53088      // Prepare the editor
53089      if (this.$editor === null) {
53090        // Create the panel
53091        var editorHeader = $('<div/>', {
53092                            'class': 'md-header btn-toolbar'
53093                            });
53094
53095        // Merge the main & additional button groups together
53096        var allBtnGroups = [];
53097        if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]);
53098        if (options.additionalButtons.length > 0) {
53099          // iterate the additional button groups
53100          $.each(options.additionalButtons[0], function(idx, buttonGroup){
53101            
53102            // see if the group name of the addional group matches an existing group
53103            var matchingGroups = $.grep(allBtnGroups, function(allButtonGroup, allIdx){
53104              return allButtonGroup.name === buttonGroup.name;
53105            });
53106
53107            // if it matches add the addional buttons to that group, if not just add it to the all buttons group
53108            if(matchingGroups.length > 0) {
53109              matchingGroups[0].data = matchingGroups[0].data.concat(buttonGroup.data);
53110            } else {              
53111              allBtnGroups.push(options.additionalButtons[0][idx]);
53112            }
53113
53114          });
53115        } 
53116
53117        // Reduce and/or reorder the button groups
53118        if (options.reorderButtonGroups.length > 0) {
53119          allBtnGroups = allBtnGroups
53120              .filter(function(btnGroup) {
53121                return options.reorderButtonGroups.indexOf(btnGroup.name) > -1;
53122              })
53123              .sort(function(a, b) {
53124                if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1;
53125                if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1;
53126                return 0;
53127              });
53128        }
53129
53130        // Build the buttons
53131        if (allBtnGroups.length > 0) {
53132          editorHeader = this.__buildButtons([allBtnGroups], editorHeader);
53133        }
53134
53135        if (options.fullscreen.enable) {
53136          editorHeader.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="'+this.__getIcon(options.fullscreen.icons.fullscreenOn)+'"></span></a></div>').on('click', '.md-control-fullscreen', function(e) {
53137              e.preventDefault();
53138              instance.setFullscreen(true);
53139          });
53140        }
53141
53142        editor.append(editorHeader);
53143
53144        // Wrap the textarea
53145        if (container.is('textarea')) {
53146          container.before(editor);
53147          textarea = container;
53148          textarea.addClass('md-input');
53149          editor.append(textarea);
53150        } else {
53151          var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),
53152              currentContent = $.trim(rawContent);
53153
53154          // This is some arbitrary content that could be edited
53155          textarea = $('<textarea/>', {
53156                       'class': 'md-input',
53157                       'val' : currentContent
53158                      });
53159
53160          editor.append(textarea);
53161
53162          // Save the editable
53163          editable.el = container;
53164          editable.type = container.prop('tagName').toLowerCase();
53165          editable.content = container.html();
53166
53167          $(container[0].attributes).each(function(){
53168            editable.attrKeys.push(this.nodeName);
53169            editable.attrValues.push(this.nodeValue);
53170          });
53171
53172          // Set editor to blocked the original container
53173          container.replaceWith(editor);
53174        }
53175
53176        var editorFooter = $('<div/>', {
53177                           'class': 'md-footer'
53178                         }),
53179            createFooter = false,
53180            footer = '';
53181        // Create the footer if savable
53182        if (options.savable) {
53183          createFooter = true;
53184          var saveHandler = 'cmdSave';
53185
53186          // Register handler and callback
53187          handler.push(saveHandler);
53188          callback.push(options.onSave);
53189
53190          editorFooter.append('<button class="btn btn-success" data-provider="'
53191                              + ns
53192                              + '" data-handler="'
53193                              + saveHandler
53194                              + '"><i class="icon icon-white icon-ok"></i> '
53195                              + this.__localize('Save')
53196                              + '</button>');
53197
53198
53199        }
53200
53201        footer = typeof options.footer === 'function' ? options.footer(this) : options.footer;
53202
53203        if ($.trim(footer) !== '') {
53204          createFooter = true;
53205          editorFooter.append(footer);
53206        }
53207
53208        if (createFooter) editor.append(editorFooter);
53209
53210        // Set width
53211        if (options.width && options.width !== 'inherit') {
53212          if (jQuery.isNumeric(options.width)) {
53213            editor.css('display', 'table');
53214            textarea.css('width', options.width + 'px');
53215          } else {
53216            editor.addClass(options.width);
53217          }
53218        }
53219
53220        // Set height
53221        if (options.height && options.height !== 'inherit') {
53222          if (jQuery.isNumeric(options.height)) {
53223            var height = options.height;
53224            if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight());
53225            if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight());
53226            textarea.css('height', height + 'px');
53227          } else {
53228            editor.addClass(options.height);
53229          }
53230        }
53231
53232        // Reference
53233        this.$editor     = editor;
53234        this.$textarea   = textarea;
53235        this.$editable   = editable;
53236        this.$oldContent = this.getContent();
53237
53238        this.__setListener();
53239
53240        // Set editor attributes, data short-hand API and listener
53241        this.$editor.attr('id',(new Date()).getTime());
53242        this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this));
53243
53244        if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
53245          this.$editor.addClass('md-editor-disabled');
53246          this.disableButtons('all');
53247        }
53248
53249        if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') {
53250          editorHeader.find('[data-provider="bootstrap-markdown"]').each(function() {
53251            var $button = $(this),
53252                hotkey = $button.attr('data-hotkey');
53253            if (hotkey.toLowerCase() !== '') {
53254              textarea.bind('keydown', hotkey, function() {
53255                $button.trigger('click');
53256                return false;
53257              });
53258            }
53259          });
53260        }
53261
53262        if (options.initialstate === 'preview') {
53263          this.showPreview();
53264        } else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) {
53265          this.setFullscreen(true);
53266        }
53267
53268      } else {
53269        this.$editor.show();
53270      }
53271
53272      if (options.autofocus) {
53273        this.$textarea.focus();
53274        this.$editor.addClass('active');
53275      }
53276
53277      if (options.fullscreen.enable && options.fullscreen !== false) {
53278        this.$editor.append('<div class="md-fullscreen-controls">'
53279                        + '<a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '">'
53280                        + '</span></a>'
53281                        + '</div>');
53282        this.$editor.on('click', '.exit-fullscreen', function(e) {
53283          e.preventDefault();
53284          instance.setFullscreen(false);
53285        });
53286      }
53287
53288      // hide hidden buttons from options
53289      this.hideButtons(options.hiddenButtons);
53290
53291      // disable disabled buttons from options
53292      this.disableButtons(options.disabledButtons);
53293
53294      // Trigger the onShow hook
53295      options.onShow(this);
53296
53297      return this;
53298    }
53299
53300  , parseContent: function(val) {
53301      var content;
53302
53303      // parse with supported markdown parser
53304      var val = val || this.$textarea.val();
53305
53306      if (this.$options.parser) {
53307        content = this.$options.parser(val);
53308      } else if (typeof markdown == 'object') {
53309        content = markdown.toHTML(val);
53310      } else if (typeof marked == 'function') {
53311        content = marked(val);
53312      } else {
53313        content = val;
53314      }
53315
53316      return content;
53317    }
53318
53319  , showPreview: function() {
53320      var options = this.$options,
53321          container = this.$textarea,
53322          afterContainer = container.next(),
53323          replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}),
53324          content,
53325          callbackContent;
53326
53327      if (this.$isPreview == true) {
53328        // Avoid sequenced element creation on missused scenario
53329        // @see https://github.com/toopay/bootstrap-markdown/issues/170
53330        return this;
53331      }
53332      
53333      // Give flag that tell the editor enter preview mode
53334      this.$isPreview = true;
53335      // Disable all buttons
53336      this.disableButtons('all').enableButtons('cmdPreview');
53337
53338      // Try to get the content from callback
53339      callbackContent = options.onPreview(this);
53340      // Set the content based from the callback content if string otherwise parse value from textarea
53341      content = typeof callbackContent == 'string' ? callbackContent : this.parseContent();
53342
53343      // Build preview element
53344      replacementContainer.html(content);
53345
53346      if (afterContainer && afterContainer.attr('class') == 'md-footer') {
53347        // If there is footer element, insert the preview container before it
53348        replacementContainer.insertBefore(afterContainer);
53349      } else {
53350        // Otherwise, just append it after textarea
53351        container.parent().append(replacementContainer);
53352      }
53353
53354      // Set the preview element dimensions
53355      replacementContainer.css({
53356        width: container.outerWidth() + 'px',
53357        height: container.outerHeight() + 'px'
53358      });
53359
53360      if (this.$options.resize) {
53361        replacementContainer.css('resize',this.$options.resize);
53362      }
53363
53364      // Hide the last-active textarea
53365      container.hide();
53366
53367      // Attach the editor instances
53368      replacementContainer.data('markdown',this);
53369
53370      if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
53371        this.$editor.addClass('md-editor-disabled');
53372        this.disableButtons('all');
53373      }
53374
53375      return this;
53376    }
53377
53378  , hidePreview: function() {
53379      // Give flag that tell the editor quit preview mode
53380      this.$isPreview = false;
53381
53382      // Obtain the preview container
53383      var container = this.$editor.find('div[data-provider="markdown-preview"]');
53384
53385      // Remove the preview container
53386      container.remove();
53387
53388      // Enable all buttons
53389      this.enableButtons('all');
53390      // Disable configured disabled buttons
53391      this.disableButtons(this.$options.disabledButtons);
53392
53393      // Back to the editor
53394      this.$textarea.show();
53395      this.__setListener();
53396
53397      return this;
53398    }
53399
53400  , isDirty: function() {
53401      return this.$oldContent != this.getContent();
53402    }
53403
53404  , getContent: function() {
53405      return this.$textarea.val();
53406    }
53407
53408  , setContent: function(content) {
53409      this.$textarea.val(content);
53410
53411      return this;
53412    }
53413
53414  , findSelection: function(chunk) {
53415    var content = this.getContent(), startChunkPosition;
53416
53417    if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {
53418      var oldSelection = this.getSelection(), selection;
53419
53420      this.setSelection(startChunkPosition,startChunkPosition+chunk.length);
53421      selection = this.getSelection();
53422
53423      this.setSelection(oldSelection.start,oldSelection.end);
53424
53425      return selection;
53426    } else {
53427      return null;
53428    }
53429  }
53430
53431  , getSelection: function() {
53432
53433      var e = this.$textarea[0];
53434
53435      return (
53436
53437          ('selectionStart' in e && function() {
53438              var l = e.selectionEnd - e.selectionStart;
53439              return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) };
53440          }) ||
53441
53442          /* browser not supported */
53443          function() {
53444            return null;
53445          }
53446
53447      )();
53448
53449    }
53450
53451  , setSelection: function(start,end) {
53452
53453      var e = this.$textarea[0];
53454
53455      return (
53456
53457          ('selectionStart' in e && function() {
53458              e.selectionStart = start;
53459              e.selectionEnd = end;
53460              return;
53461          }) ||
53462
53463          /* browser not supported */
53464          function() {
53465            return null;
53466          }
53467
53468      )();
53469
53470    }
53471
53472  , replaceSelection: function(text) {
53473
53474      var e = this.$textarea[0];
53475
53476      return (
53477
53478          ('selectionStart' in e && function() {
53479              e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length);
53480              // Set cursor to the last replacement end
53481              e.selectionStart = e.value.length;
53482              return this;
53483          }) ||
53484
53485          /* browser not supported */
53486          function() {
53487              e.value += text;
53488              return jQuery(e);
53489          }
53490
53491      )();
53492    }
53493
53494  , getNextTab: function() {
53495      // Shift the nextTab
53496      if (this.$nextTab.length === 0) {
53497        return null;
53498      } else {
53499        var nextTab, tab = this.$nextTab.shift();
53500
53501        if (typeof tab == 'function') {
53502          nextTab = tab();
53503        } else if (typeof tab == 'object' && tab.length > 0) {
53504          nextTab = tab;
53505        }
53506
53507        return nextTab;
53508      }
53509    }
53510
53511  , setNextTab: function(start,end) {
53512      // Push new selection into nextTab collections
53513      if (typeof start == 'string') {
53514        var that = this;
53515        this.$nextTab.push(function(){
53516          return that.findSelection(start);
53517        });
53518      } else if (typeof start == 'number' && typeof end == 'number') {
53519        var oldSelection = this.getSelection();
53520
53521        this.setSelection(start,end);
53522        this.$nextTab.push(this.getSelection());
53523
53524        this.setSelection(oldSelection.start,oldSelection.end);
53525      }
53526
53527      return;
53528    }
53529
53530  , __parseButtonNameParam: function (names) {
53531      return typeof names == 'string' ?
53532                      names.split(' ') :
53533                      names;
53534
53535    }
53536
53537  , enableButtons: function(name) {
53538      var buttons = this.__parseButtonNameParam(name),
53539        that = this;
53540
53541      $.each(buttons, function(i, v) {
53542        that.__alterButtons(buttons[i], function (el) {
53543          el.removeAttr('disabled');
53544        });
53545      });
53546
53547      return this;
53548    }
53549
53550  , disableButtons: function(name) {
53551      var buttons = this.__parseButtonNameParam(name),
53552        that = this;
53553
53554      $.each(buttons, function(i, v) {
53555        that.__alterButtons(buttons[i], function (el) {
53556          el.attr('disabled','disabled');
53557        });
53558      });
53559
53560      return this;
53561    }
53562
53563  , hideButtons: function(name) {
53564      var buttons = this.__parseButtonNameParam(name),
53565        that = this;
53566
53567      $.each(buttons, function(i, v) {
53568        that.__alterButtons(buttons[i], function (el) {
53569          el.addClass('hidden');
53570        });
53571      });
53572
53573      return this;
53574    }
53575
53576  , showButtons: function(name) {
53577      var buttons = this.__parseButtonNameParam(name),
53578        that = this;
53579
53580      $.each(buttons, function(i, v) {
53581        that.__alterButtons(buttons[i], function (el) {
53582          el.removeClass('hidden');
53583        });
53584      });
53585
53586      return this;
53587    }
53588
53589  , eventSupported: function(eventName) {
53590      var isSupported = eventName in this.$element;
53591      if (!isSupported) {
53592        this.$element.setAttribute(eventName, 'return;');
53593        isSupported = typeof this.$element[eventName] === 'function';
53594      }
53595      return isSupported;
53596    }
53597
53598  , keyup: function (e) {
53599      var blocked = false;
53600      switch(e.keyCode) {
53601        case 40: // down arrow
53602        case 38: // up arrow
53603        case 16: // shift
53604        case 17: // ctrl
53605        case 18: // alt
53606          break;
53607
53608        case 9: // tab
53609          var nextTab;
53610          if (nextTab = this.getNextTab(),nextTab !== null) {
53611            // Get the nextTab if exists
53612            var that = this;
53613            setTimeout(function(){
53614              that.setSelection(nextTab.start,nextTab.end);
53615            },500);
53616
53617            blocked = true;
53618          } else {
53619            // The next tab memory contains nothing...
53620            // check the cursor position to determine tab action
53621            var cursor = this.getSelection();
53622
53623            if (cursor.start == cursor.end && cursor.end == this.getContent().length) {
53624              // The cursor already reach the end of the content
53625              blocked = false;
53626            } else {
53627              // Put the cursor to the end
53628              this.setSelection(this.getContent().length,this.getContent().length);
53629
53630              blocked = true;
53631            }
53632          }
53633
53634          break;
53635
53636        case 13: // enter
53637          blocked = false;
53638          break;
53639        case 27: // escape
53640          if (this.$isFullscreen) this.setFullscreen(false);
53641          blocked = false;
53642          break;
53643
53644        default:
53645          blocked = false;
53646      }
53647
53648      if (blocked) {
53649        e.stopPropagation();
53650        e.preventDefault();
53651      }
53652
53653      this.$options.onChange(this);
53654    }
53655
53656  , change: function(e) {
53657      this.$options.onChange(this);
53658      return this;
53659    }
53660  , select: function (e) {
53661      this.$options.onSelect(this);
53662      return this;
53663    }
53664  , focus: function (e) {
53665      var options = this.$options,
53666          isHideable = options.hideable,
53667          editor = this.$editor;
53668
53669      editor.addClass('active');
53670
53671      // Blur other markdown(s)
53672      $(document).find('.md-editor').each(function(){
53673        if ($(this).attr('id') !== editor.attr('id')) {
53674          var attachedMarkdown;
53675
53676          if (attachedMarkdown = $(this).find('textarea').data('markdown'),
53677              attachedMarkdown === null) {
53678              attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown');
53679          }
53680
53681          if (attachedMarkdown) {
53682            attachedMarkdown.blur();
53683          }
53684        }
53685      });
53686
53687      // Trigger the onFocus hook
53688      options.onFocus(this);
53689
53690      return this;
53691    }
53692
53693  , blur: function (e) {
53694      var options = this.$options,
53695          isHideable = options.hideable,
53696          editor = this.$editor,
53697          editable = this.$editable;
53698
53699      if (editor.hasClass('active') || this.$element.parent().length === 0) {
53700        editor.removeClass('active');
53701
53702        if (isHideable) {
53703          // Check for editable elements
53704          if (editable.el !== null) {
53705            // Build the original element
53706            var oldElement = $('<'+editable.type+'/>'),
53707                content = this.getContent(),
53708                currentContent = this.parseContent(content);
53709
53710            $(editable.attrKeys).each(function(k,v) {
53711              oldElement.attr(editable.attrKeys[k],editable.attrValues[k]);
53712            });
53713
53714            // Get the editor content
53715            oldElement.html(currentContent);
53716
53717            editor.replaceWith(oldElement);
53718          } else {
53719            editor.hide();
53720          }
53721        }
53722
53723        // Trigger the onBlur hook
53724        options.onBlur(this);
53725      }
53726
53727      return this;
53728    }
53729
53730  };
53731
53732 /* MARKDOWN PLUGIN DEFINITION
53733  * ========================== */
53734
53735  var old = $.fn.markdown;
53736
53737  $.fn.markdown = function (option) {
53738    return this.each(function () {
53739      var $this = $(this)
53740        , data = $this.data('markdown')
53741        , options = typeof option == 'object' && option;
53742      if (!data) $this.data('markdown', (data = new Markdown(this, options)))
53743    })
53744  };
53745
53746  $.fn.markdown.messages = {};
53747
53748  $.fn.markdown.defaults = {
53749    /* Editor Properties */
53750    autofocus: false,
53751    hideable: false,
53752    savable: false,
53753    width: 'inherit',
53754    height: 'inherit',
53755    resize: 'none',
53756    iconlibrary: 'glyph',
53757    language: 'en',
53758    initialstate: 'editor',
53759    parser: null,
53760
53761    /* Buttons Properties */
53762    buttons: [
53763      [{
53764        name: 'groupFont',
53765        data: [{
53766          name: 'cmdBold',
53767          hotkey: 'Ctrl+B',
53768          title: 'Bold',
53769          icon: { glyph: 'glyphicon glyphicon-bold', fa: 'fa fa-bold', 'fa-3': 'icon-bold' },
53770          callback: function(e){
53771            // Give/remove ** surround the selection
53772            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
53773
53774            if (selected.length === 0) {
53775              // Give extra word
53776              chunk = e.__localize('strong text');
53777            } else {
53778              chunk = selected.text;
53779            }
53780
53781            // transform selection and set the cursor into chunked text
53782            if (content.substr(selected.start-2,2) === '**'
53783                && content.substr(selected.end,2) === '**' ) {
53784              e.setSelection(selected.start-2,selected.end+2);
53785              e.replaceSelection(chunk);
53786              cursor = selected.start-2;
53787            } else {
53788              e.replaceSelection('**'+chunk+'**');
53789              cursor = selected.start+2;
53790            }
53791
53792            // Set the cursor
53793            e.setSelection(cursor,cursor+chunk.length);
53794          }
53795        },{
53796          name: 'cmdItalic',
53797          title: 'Italic',
53798          hotkey: 'Ctrl+I',
53799          icon: { glyph: 'glyphicon glyphicon-italic', fa: 'fa fa-italic', 'fa-3': 'icon-italic' },
53800          callback: function(e){
53801            // Give/remove * surround the selection
53802            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
53803
53804            if (selected.length === 0) {
53805              // Give extra word
53806              chunk = e.__localize('emphasized text');
53807            } else {
53808              chunk = selected.text;
53809            }
53810
53811            // transform selection and set the cursor into chunked text
53812            if (content.substr(selected.start-1,1) === '_'
53813                && content.substr(selected.end,1) === '_' ) {
53814              e.setSelection(selected.start-1,selected.end+1);
53815              e.replaceSelection(chunk);
53816              cursor = selected.start-1;
53817            } else {
53818              e.replaceSelection('_'+chunk+'_');
53819              cursor = selected.start+1;
53820            }
53821
53822            // Set the cursor
53823            e.setSelection(cursor,cursor+chunk.length);
53824          }
53825        },{
53826          name: 'cmdHeading',
53827          title: 'Heading',
53828          hotkey: 'Ctrl+H',
53829          icon: { glyph: 'glyphicon glyphicon-header', fa: 'fa fa-header', 'fa-3': 'icon-font' },
53830          callback: function(e){
53831            // Append/remove ### surround the selection
53832            var chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar;
53833
53834            if (selected.length === 0) {
53835              // Give extra word
53836              chunk = e.__localize('heading text');
53837            } else {
53838              chunk = selected.text + '\n';
53839            }
53840
53841            // transform selection and set the cursor into chunked text
53842            if ((pointer = 4, content.substr(selected.start-pointer,pointer) === '### ')
53843                || (pointer = 3, content.substr(selected.start-pointer,pointer) === '###')) {
53844              e.setSelection(selected.start-pointer,selected.end);
53845              e.replaceSelection(chunk);
53846              cursor = selected.start-pointer;
53847            } else if (selected.start > 0 && (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n')) {
53848              e.replaceSelection('\n\n### '+chunk);
53849              cursor = selected.start+6;
53850            } else {
53851              // Empty string before element
53852              e.replaceSelection('### '+chunk);
53853              cursor = selected.start+4;
53854            }
53855
53856            // Set the cursor
53857            e.setSelection(cursor,cursor+chunk.length);
53858          }
53859        }]
53860      },{
53861        name: 'groupLink',
53862        data: [{
53863          name: 'cmdUrl',
53864          title: 'URL/Link',
53865          hotkey: 'Ctrl+L',
53866          icon: { glyph: 'glyphicon glyphicon-link', fa: 'fa fa-link', 'fa-3': 'icon-link' },
53867          callback: function(e){
53868            // Give [] surround the selection and prepend the link
53869            var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
53870
53871            if (selected.length === 0) {
53872              // Give extra word
53873              chunk = e.__localize('enter link description here');
53874            } else {
53875              chunk = selected.text;
53876            }
53877
53878            link = prompt(e.__localize('Insert Hyperlink'),'http://');
53879
53880            var urlRegex = new RegExp('^((http|https)://|(mailto:)|(//))[a-z0-9]', 'i');
53881            if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
53882              var sanitizedLink = $('<div>'+link+'</div>').text();
53883
53884              // transform selection and set the cursor into chunked text
53885              e.replaceSelection('['+chunk+']('+sanitizedLink+')');
53886              cursor = selected.start+1;
53887
53888              // Set the cursor
53889              e.setSelection(cursor,cursor+chunk.length);
53890            }
53891          }
53892        },{
53893          name: 'cmdImage',
53894          title: 'Image',
53895          hotkey: 'Ctrl+G',
53896          icon: { glyph: 'glyphicon glyphicon-picture', fa: 'fa fa-picture-o', 'fa-3': 'icon-picture' },
53897          callback: function(e){
53898            // Give ![] surround the selection and prepend the image link
53899            var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
53900
53901            if (selected.length === 0) {
53902              // Give extra word
53903              chunk = e.__localize('enter image description here');
53904            } else {
53905              chunk = selected.text;
53906            }
53907
53908            link = prompt(e.__localize('Insert Image Hyperlink'),'http://');
53909
53910            var urlRegex = new RegExp('^((http|https)://|(//))[a-z0-9]', 'i');
53911            if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
53912              var sanitizedLink = $('<div>'+link+'</div>').text();
53913
53914              // transform selection and set the cursor into chunked text
53915              e.replaceSelection('!['+chunk+']('+sanitizedLink+' "'+e.__localize('enter image title here')+'")');
53916              cursor = selected.start+2;
53917
53918              // Set the next tab
53919              e.setNextTab(e.__localize('enter image title here'));
53920
53921              // Set the cursor
53922              e.setSelection(cursor,cursor+chunk.length);
53923            }
53924          }
53925        }]
53926      },{
53927        name: 'groupMisc',
53928        data: [{
53929          name: 'cmdList',
53930          hotkey: 'Ctrl+U',
53931          title: 'Unordered List',
53932          icon: { glyph: 'glyphicon glyphicon-list', fa: 'fa fa-list', 'fa-3': 'icon-list-ul' },
53933          callback: function(e){
53934            // Prepend/Give - surround the selection
53935            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
53936
53937            // transform selection and set the cursor into chunked text
53938            if (selected.length === 0) {
53939              // Give extra word
53940              chunk = e.__localize('list text here');
53941
53942              e.replaceSelection('- '+chunk);
53943              // Set the cursor
53944              cursor = selected.start+2;
53945            } else {
53946              if (selected.text.indexOf('\n') < 0) {
53947                chunk = selected.text;
53948
53949                e.replaceSelection('- '+chunk);
53950
53951                // Set the cursor
53952                cursor = selected.start+2;
53953              } else {
53954                var list = [];
53955
53956                list = selected.text.split('\n');
53957                chunk = list[0];
53958
53959                $.each(list,function(k,v) {
53960                  list[k] = '- '+v;
53961                });
53962
53963                e.replaceSelection('\n\n'+list.join('\n'));
53964
53965                // Set the cursor
53966                cursor = selected.start+4;
53967              }
53968            }
53969
53970            // Set the cursor
53971            e.setSelection(cursor,cursor+chunk.length);
53972          }
53973        },
53974        {
53975          name: 'cmdListO',
53976          hotkey: 'Ctrl+O',
53977          title: 'Ordered List',
53978          icon: { glyph: 'glyphicon glyphicon-th-list', fa: 'fa fa-list-ol', 'fa-3': 'icon-list-ol' },
53979          callback: function(e) {
53980
53981            // Prepend/Give - surround the selection
53982            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
53983
53984            // transform selection and set the cursor into chunked text
53985            if (selected.length === 0) {
53986              // Give extra word
53987              chunk = e.__localize('list text here');
53988              e.replaceSelection('1. '+chunk);
53989              // Set the cursor
53990              cursor = selected.start+3;
53991            } else {
53992              if (selected.text.indexOf('\n') < 0) {
53993                chunk = selected.text;
53994
53995                e.replaceSelection('1. '+chunk);
53996
53997                // Set the cursor
53998                cursor = selected.start+3;
53999              } else {
54000                var list = [];
54001
54002                list = selected.text.split('\n');
54003                chunk = list[0];
54004
54005                $.each(list,function(k,v) {
54006                  list[k] = '1. '+v;
54007                });
54008
54009                e.replaceSelection('\n\n'+list.join('\n'));
54010
54011                // Set the cursor
54012                cursor = selected.start+5;
54013              }
54014            }
54015
54016            // Set the cursor
54017            e.setSelection(cursor,cursor+chunk.length);
54018          }
54019        },
54020        {
54021          name: 'cmdCode',
54022          hotkey: 'Ctrl+K',
54023          title: 'Code',
54024          icon: { glyph: 'glyphicon glyphicon-asterisk', fa: 'fa fa-code', 'fa-3': 'icon-code' },
54025          callback: function(e) {
54026            // Give/remove ** surround the selection
54027            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
54028
54029            if (selected.length === 0) {
54030              // Give extra word
54031              chunk = e.__localize('code text here');
54032            } else {
54033              chunk = selected.text;
54034            }
54035
54036            // transform selection and set the cursor into chunked text
54037            if (content.substr(selected.start-4,4) === '```\n'
54038                && content.substr(selected.end,4) === '\n```') {
54039              e.setSelection(selected.start-4, selected.end+4);
54040              e.replaceSel
54040ection(chunk);
54041              cursor = selected.start-4;
54042            } else if (content.substr(selected.start-1,1) === '`'
54043                && content.substr(selected.end,1) === '`') {
54044              e.setSelection(selected.start-1,selected.end+1);
54045              e.replaceSelection(chunk);
54046              cursor = selected.start-1;
54047            } else if (content.indexOf('\n') > -1) {
54048              e.replaceSelection('```\n'+chunk+'\n```');
54049              cursor = selected.start+4;
54050            } else {
54051              e.replaceSelection('`'+chunk+'`');
54052              cursor = selected.start+1;
54053            }
54054
54055            // Set the cursor
54056            e.setSelection(cursor,cursor+chunk.length);
54057          }
54058        },
54059        {
54060          name: 'cmdQuote',
54061          hotkey: 'Ctrl+Q',
54062          title: 'Quote',
54063          icon: { glyph: 'glyphicon glyphicon-comment', fa: 'fa fa-quote-left', 'fa-3': 'icon-quote-left' },
54064          callback: function(e) {
54065            // Prepend/Give - surround the selection
54066            var chunk, cursor, selected = e.getSelection(), content = e.getContent();
54067
54068            // transform selection and set the cursor into chunked text
54069            if (selected.length === 0) {
54070              // Give extra word
54071              chunk = e.__localize('quote here');
54072
54073              e.replaceSelection('> '+chunk);
54074
54075              // Set the cursor
54076              cursor = selected.start+2;
54077            } else {
54078              if (selected.text.indexOf('\n') < 0) {
54079                chunk = selected.text;
54080
54081                e.replaceSelection('> '+chunk);
54082
54083                // Set the cursor
54084                cursor = selected.start+2;
54085              } else {
54086                var list = [];
54087
54088                list = selected.text.split('\n');
54089                chunk = list[0];
54090
54091                $.each(list,function(k,v) {
54092                  list[k] = '> '+v;
54093                });
54094
54095                e.replaceSelection('\n\n'+list.join('\n'));
54096
54097                // Set the cursor
54098                cursor = selected.start+4;
54099              }
54100            }
54101
54102            // Set the cursor
54103            e.setSelection(cursor,cursor+chunk.length);
54104          }
54105        }]
54106      },{
54107        name: 'groupUtil',
54108        data: [{
54109          name: 'cmdPreview',
54110          toggle: true,
54111          hotkey: 'Ctrl+P',
54112          title: 'Preview',
54113          btnText: 'Preview',
54114          btnClass: 'btn btn-primary btn-sm',
54115          icon: { glyph: 'glyphicon glyphicon-search', fa: 'fa fa-search', 'fa-3': 'icon-search' },
54116          callback: function(e){
54117            // Check the preview mode and toggle based on this flag
54118            var isPreview = e.$isPreview,content;
54119
54120            if (isPreview === false) {
54121              // Give flag that tell the editor enter preview mode
54122              e.showPreview();
54123            } else {
54124              e.hidePreview();
54125            }
54126          }
54127        }]
54128      }]
54129    ],
54130    additionalButtons:[], // Place to hook more buttons by code
54131    reorderButtonGroups:[],
54132    hiddenButtons:[], // Default hidden buttons
54133    disabledButtons:[], // Default disabled buttons
54134    footer: '',
54135    fullscreen: {
54136      enable: true,
54137      icons: {
54138        fullscreenOn: {
54139          fa: 'fa fa-expand',
54140          glyph: 'glyphicon glyphicon-fullscreen',
54141          'fa-3': 'icon-resize-full'
54142        },
54143        fullscreenOff: {
54144          fa: 'fa fa-compress',
54145          glyph: 'glyphicon glyphicon-fullscreen',
54146          'fa-3': 'icon-resize-small'
54147        }
54148      }
54149    },
54150
54151    /* Events hook */
54152    onShow: function (e) {},
54153    onPreview: function (e) {},
54154    onSave: function (e) {},
54155    onBlur: function (e) {},
54156    onFocus: function (e) {},
54157    onChange: function(e) {},
54158    onFullscreen: function(e) {},
54159    onSelect: function (e) {}
54160  };
54161
54162  $.fn.markdown.Constructor = Markdown;
54163
54164
54165 /* MARKDOWN NO CONFLICT
54166  * ==================== */
54167
54168  $.fn.markdown.noConflict = function () {
54169    $.fn.markdown = old;
54170    return this;
54171  };
54172
54173  /* MARKDOWN GLOBAL FUNCTION & DATA-API
54174  * ==================================== */
54175  var initMarkdown = function(el) {
54176    var $this = el;
54177
54178    if ($this.data('markdown')) {
54179      $this.data('markdown').showEditor();
54180      return;
54181    }
54182
54183    $this.markdown()
54184  };
54185
54186  var blurNonFocused = function(e) {
54187    var $activeElement = $(document.activeElement);
54188
54189    // Blur event
54190    $(document).find('.md-editor').each(function(){
54191      var $this            = $(this),
54192          focused          = $activeElement.closest('.md-editor')[0] === this,
54193          attachedMarkdown = $this.find('textarea').data('markdown') ||
54194                             $this.find('div[data-provider="markdown-preview"]').data('markdown');
54195
54196      if (attachedMarkdown && !focused) {
54197        attachedMarkdown.blur();
54198      }
54199    })
54200  };
54201
54202  $(document)
vendor: 8,498 bytes, lines 54203-54511
54203    .on('click.markdown.data-api', '[data-provide="markdown-editable"]', function (e) {
54204      initMarkdown($(this));
54205      e.preventDefault();
54206    })
54207    .on('click focusin', function (e) {
54208      blurNonFocused(e);
54209    })
54210    .ready(function(){
54211      $('textarea[data-provide="markdown"]').each(function(){
54212        initMarkdown($(this));
54213      })
54214    });
54215
54216}));
54217
54218"use strict";
54219$.fn.markdown.defaults.iconlibrary = 'fa';
54220$.fn.markdown.defaults.buttons[0][0]['data'][2]['icon']['fa'] = 'fa fa-heading';
54221$.fn.markdown.defaults.buttons[0][1]['data'][1]['icon']['fa'] = 'fa fa-image';
54222$.fn.markdown.defaults.buttons[0][2]['data'][1]['icon']['fa'] = 'fa fa-list-ol';
54223
54224/*!
54225 * jQuery Validation Plugin v1.19.0
54226 *
54227 * https://jqueryvalidation.org/
54228 *
54229 * Copyright (c) 2018 Jörn Zaefferer
54230 * Released under the MIT license
54231 */
54232(function( factory ) {
54233	if ( typeof define === "function" && define.amd ) {
54234		define( ["jquery"], factory );
54235	} else if (typeof module === "object" && module.exports) {
54236		module.exports = factory( require( "jquery" ) );
54237	} else {
54238		factory( jQuery );
54239	}
54240}(function( $ ) {
54241
54242$.extend( $.fn, {
54243
54244	// https://jqueryvalidation.org/validate/
54245	validate: function( options ) {
54246
54247		// If nothing is selected, return nothing; can't chain anyway
54248		if ( !this.length ) {
54249			if ( options && options.debug && window.console ) {
54250				console.warn( "Nothing selected, can't validate, returning nothing." );
54251			}
54252			return;
54253		}
54254
54255		// Check if a validator for this form was already created
54256		var validator = $.data( this[ 0 ], "validator" );
54257		if ( validator ) {
54258			return validator;
54259		}
54260
54261		// Add novalidate tag if HTML5.
54262		this.attr( "novalidate", "novalidate" );
54263
54264		validator = new $.validator( options, this[ 0 ] );
54265		$.data( this[ 0 ], "validator", validator );
54266
54267		if ( validator.settings.onsubmit ) {
54268
54269			this.on( "click.validate", ":submit", function( event ) {
54270
54271				// Track the used submit button to properly handle scripted
54272				// submits later.
54273				validator.submitButton = event.currentTarget;
54274
54275				// Allow suppressing validation by adding a cancel class to the submit button
54276				if ( $( this ).hasClass( "cancel" ) ) {
54277					validator.cancelSubmit = true;
54278				}
54279
54280				// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
54281				if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
54282					validator.cancelSubmit = true;
54283				}
54284			} );
54285
54286			// Validate the form on submit
54287			this.on( "submit.validate", function( event ) {
54288				if ( validator.settings.debug ) {
54289
54290					// Prevent form submit to be able to see console output
54291					event.preventDefault();
54292				}
54293
54294				function handle() {
54295					var hidden, result;
54296
54297					// Insert a hidden input as a replacement for the missing submit button
54298					// The hidden input is inserted in two cases:
54299					//   - A user defined a `submitHandler`
54300					//   - There was a pending request due to `remote` method and `stopRequest()`
54301					//     was called to submit the form in case it's valid
54302					if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) {
54303						hidden = $( "<input type='hidden'/>" )
54304							.attr( "name", validator.submitButton.name )
54305							.val( $( validator.submitButton ).val() )
54306							.appendTo( validator.currentForm );
54307					}
54308
54309					if ( validator.settings.submitHandler && !validator.settings.debug ) {
54310						result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
54311						if ( hidden ) {
54312
54313							// And clean up afterwards; thanks to no-block-scope, hidden can be referenced
54314							hidden.remove();
54315						}
54316						if ( result !== undefined ) {
54317							return result;
54318						}
54319						return false;
54320					}
54321					return true;
54322				}
54323
54324				// Prevent submit for invalid forms or custom submit handlers
54325				if ( validator.cancelSubmit ) {
54326					validator.cancelSubmit = false;
54327					return handle();
54328				}
54329				if ( validator.form() ) {
54330					if ( validator.pendingRequest ) {
54331						validator.formSubmitted = true;
54332						return false;
54333					}
54334					return handle();
54335				} else {
54336					validator.focusInvalid();
54337					return false;
54338				}
54339			} );
54340		}
54341
54342		return validator;
54343	},
54344
54345	// https://jqueryvalidation.org/valid/
54346	valid: function() {
54347		var valid, validator, errorList;
54348
54349		if ( $( this[ 0 ] ).is( "form" ) ) {
54350			valid = this.validate().form();
54351		} else {
54352			errorList = [];
54353			valid = true;
54354			validator = $( this[ 0 ].form ).validate();
54355			this.each( function() {
54356				valid = validator.element( this ) && valid;
54357				if ( !valid ) {
54358					errorList = errorList.concat( validator.errorList );
54359				}
54360			} );
54361			validator.errorList = errorList;
54362		}
54363		return valid;
54364	},
54365
54366	// https://jqueryvalidation.org/rules/
54367	rules: function( command, argument ) {
54368		var element = this[ 0 ],
54369			isContentEditable = typeof this.attr( "contenteditable" ) !== "undefined" && this.attr( "contenteditable" ) !== "false",
54370			settings, staticRules, existingRules, data, param, filtered;
54371
54372		// If nothing is selected, return empty object; can't chain anyway
54373		if ( element == null ) {
54374			return;
54375		}
54376
54377		if ( !element.form && isContentEditable ) {
54378			element.form = this.closest( "form" )[ 0 ];
54379			element.name = this.attr( "name" );
54380		}
54381
54382		if ( element.form == null ) {
54383			return;
54384		}
54385
54386		if ( command ) {
54387			settings = $.data( element.form, "validator" ).settings;
54388			staticRules = settings.rules;
54389			existingRules = $.validator.staticRules( element );
54390			switch ( command ) {
54391			case "add":
54392				$.extend( existingRules, $.validator.normalizeRule( argument ) );
54393
54394				// Remove messages from rules, but allow them to be set separately
54395				delete existingRules.messages;
54396				staticRules[ element.name ] = existingRules;
54397				if ( argument.messages ) {
54398					settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
54399				}
54400				break;
54401			case "remove":
54402				if ( !argument ) {
54403					delete staticRules[ element.name ];
54404					return existingRules;
54405				}
54406				filtered = {};
54407				$.each( argument.split( /\s/ ), function( index, method ) {
54408					filtered[ method ] = existingRules[ method ];
54409					delete existingRules[ method ];
54410				} );
54411				return filtered;
54412			}
54413		}
54414
54415		data = $.validator.normalizeRules(
54416		$.extend(
54417			{},
54418			$.validator.classRules( element ),
54419			$.validator.attributeRules( element ),
54420			$.validator.dataRules( element ),
54421			$.validator.staticRules( element )
54422		), element );
54423
54424		// Make sure required is at front
54425		if ( data.required ) {
54426			param = data.required;
54427			delete data.required;
54428			data = $.extend( { required: param }, data );
54429		}
54430
54431		// Make sure remote is at back
54432		if ( data.remote ) {
54433			param = data.remote;
54434			delete data.remote;
54435			data = $.extend( data, { remote: param } );
54436		}
54437
54438		return data;
54439	}
54440} );
54441
54442// Custom selectors
54443$.extend( $.expr.pseudos || $.expr[ ":" ], {		// '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
54444
54445	// https://jqueryvalidation.org/blank-selector/
54446	blank: function( a ) {
54447		return !$.trim( "" + $( a ).val() );
54448	},
54449
54450	// https://jqueryvalidation.org/filled-selector/
54451	filled: function( a ) {
54452		var val = $( a ).val();
54453		return val !== null && !!$.trim( "" + val );
54454	},
54455
54456	// https://jqueryvalidation.org/unchecked-selector/
54457	unchecked: function( a ) {
54458		return !$( a ).prop( "checked" );
54459	}
54460} );
54461
54462// Constructor for validator
54463$.validator = function( options, form ) {
54464	this.settings = $.extend( true, {}, $.validator.defaults, options );
54465	this.currentForm = form;
54466	this.init();
54467};
54468
54469// https://jqueryvalidation.org/jQuery.validator.format/
54470$.validator.format = function( source, params ) {
54471	if ( arguments.length === 1 ) {
54472		return function() {
54473			var args = $.makeArray( arguments );
54474			args.unshift( source );
54475			return $.validator.format.apply( this, args );
54476		};
54477	}
54478	if ( params === undefined ) {
54479		return source;
54480	}
54481	if ( arguments.length > 2 && params.constructor !== Array  ) {
54482		params = $.makeArray( arguments ).slice( 1 );
54483	}
54484	if ( params.constructor !== Array ) {
54485		params = [ params ];
54486	}
54487	$.each( params, function( i, n ) {
54488		source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
54489			return n;
54490		} );
54491	} );
54492	return source;
54493};
54494
54495$.extend( $.validator, {
54496
54497	defaults: {
54498		messages: {},
54499		groups: {},
54500		rules: {},
54501		errorClass: "error",
54502		pendingClass: "pending",
54503		validClass: "valid",
54504		errorElement: "label",
54505		focusCleanup: false,
54506		focusInvalid: true,
54507		errorContainer: $( [] ),
54508		errorLabelContainer: $( [] ),
54509		onsubmit: true,
54510		ignore: ":hidden",
54511		ignoreTitle: false
vendor: 5,102 bytes, lines 54511-54658
54511,
54512		onfocusin: function( element ) {
54513			this.lastActive = element;
54514
54515			// Hide error label and remove error class on focus if enabled
54516			if ( this.settings.focusCleanup ) {
54517				if ( this.settings.unhighlight ) {
54518					this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
54519				}
54520				this.hideThese( this.errorsFor( element ) );
54521			}
54522		},
54523		onfocusout: function( element ) {
54524			if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
54525				this.element( element );
54526			}
54527		},
54528		onkeyup: function( element, event ) {
54529
54530			// Avoid revalidate the field when pressing one of the following keys
54531			// Shift       => 16
54532			// Ctrl        => 17
54533			// Alt         => 18
54534			// Caps lock   => 20
54535			// End         => 35
54536			// Home        => 36
54537			// Left arrow  => 37
54538			// Up arrow    => 38
54539			// Right arrow => 39
54540			// Down arrow  => 40
54541			// Insert      => 45
54542			// Num lock    => 144
54543			// AltGr key   => 225
54544			var excludedKeys = [
54545				16, 17, 18, 20, 35, 36, 37,
54546				38, 39, 40, 45, 144, 225
54547			];
54548
54549			if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
54550				return;
54551			} else if ( element.name in this.submitted || element.name in this.invalid ) {
54552				this.element( element );
54553			}
54554		},
54555		onclick: function( element ) {
54556
54557			// Click on selects, radiobuttons and checkboxes
54558			if ( element.name in this.submitted ) {
54559				this.element( element );
54560
54561			// Or option elements, check parent select in that case
54562			} else if ( element.parentNode.name in this.submitted ) {
54563				this.element( element.parentNode );
54564			}
54565		},
54566		highlight: function( element, errorClass, validClass ) {
54567			if ( element.type === "radio" ) {
54568				this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
54569			} else {
54570				$( element ).addClass( errorClass ).removeClass( validClass );
54571			}
54572		},
54573		unhighlight: function( element, errorClass, validClass ) {
54574			if ( element.type === "radio" ) {
54575				this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
54576			} else {
54577				$( element ).removeClass( errorClass ).addClass( validClass );
54578			}
54579		}
54580	},
54581
54582	// https://jqueryvalidation.org/jQuery.validator.setDefaults/
54583	setDefaults: function( settings ) {
54584		$.extend( $.validator.defaults, settings );
54585	},
54586
54587	messages: {
54588		required: "This field is required.",
54589		remote: "Please fix this field.",
54590		email: "Please enter a valid email address.",
54591		url: "Please enter a valid URL.",
54592		date: "Please enter a valid date.",
54593		dateISO: "Please enter a valid date (ISO).",
54594		number: "Please enter a valid number.",
54595		digits: "Please enter only digits.",
54596		equalTo: "Please enter the same value again.",
54597		maxlength: $.validator.format( "Please enter no more than {0} characters." ),
54598		minlength: $.validator.format( "Please enter at least {0} characters." ),
54599		rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
54600		range: $.validator.format( "Please enter a value between {0} and {1}." ),
54601		max: $.validator.format( "Please enter a value less than or equal to {0}." ),
54602		min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
54603		step: $.validator.format( "Please enter a multiple of {0}." )
54604	},
54605
54606	autoCreateRanges: false,
54607
54608	prototype: {
54609
54610		init: function() {
54611			this.labelContainer = $( this.settings.errorLabelContainer );
54612			this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
54613			this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
54614			this.submitted = {};
54615			this.valueCache = {};
54616			this.pendingRequest = 0;
54617			this.pending = {};
54618			this.invalid = {};
54619			this.reset();
54620
54621			var currentForm = this.currentForm,
54622				groups = ( this.groups = {} ),
54623				rules;
54624			$.each( this.settings.groups, function( key, value ) {
54625				if ( typeof value === "string" ) {
54626					value = value.split( /\s/ );
54627				}
54628				$.each( value, function( index, name ) {
54629					groups[ name ] = key;
54630				} );
54631			} );
54632			rules = this.settings.rules;
54633			$.each( rules, function( key, value ) {
54634				rules[ key ] = $.validator.normalizeRule( value );
54635			} );
54636
54637			function delegate( event ) {
54638				var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
54639
54640				// Set form expando on contenteditable
54641				if ( !this.form && isContentEditable ) {
54642					this.form = $( this ).closest( "form" )[ 0 ];
54643					this.name = $( this ).attr( "name" );
54644				}
54645
54646				// Ignore the element if it belongs to another form. This will happen mainly
54647				// when setting the `form` attribute of an input to the id of another form.
54648				if ( currentForm !== this.form ) {
54649					return;
54650				}
54651
54652				var validator = $.data( this.form, "validator" ),
54653					eventType = "on" + event.type.replace( /^validate/, "" ),
54654					settings = validator.settings;
54655				if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
54656					settings[ eventType ].call( validator, this, event );
54657				}
54658			}
vendor: 38,493 bytes, lines 54659-55903
54659
54660			$( this.currentForm )
54661				.on( "focusin.validate focusout.validate keyup.validate",
54662					":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
54663					"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
54664					"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
54665					"[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate )
54666
54667				// Support: Chrome, oldIE
54668				// "select" is provided as event.target when clicking a option
54669				.on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate );
54670
54671			if ( this.settings.invalidHandler ) {
54672				$( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
54673			}
54674		},
54675
54676		// https://jqueryvalidation.org/Validator.form/
54677		form: function() {
54678			this.checkForm();
54679			$.extend( this.submitted, this.errorMap );
54680			this.invalid = $.extend( {}, this.errorMap );
54681			if ( !this.valid() ) {
54682				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
54683			}
54684			this.showErrors();
54685			return this.valid();
54686		},
54687
54688		checkForm: function() {
54689			this.prepareForm();
54690			for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
54691				this.check( elements[ i ] );
54692			}
54693			return this.valid();
54694		},
54695
54696		// https://jqueryvalidation.org/Validator.element/
54697		element: function( element ) {
54698			var cleanElement = this.clean( element ),
54699				checkElement = this.validationTargetFor( cleanElement ),
54700				v = this,
54701				result = true,
54702				rs, group;
54703
54704			if ( checkElement === undefined ) {
54705				delete this.invalid[ cleanElement.name ];
54706			} else {
54707				this.prepareElement( checkElement );
54708				this.currentElements = $( checkElement );
54709
54710				// If this element is grouped, then validate all group elements already
54711				// containing a value
54712				group = this.groups[ checkElement.name ];
54713				if ( group ) {
54714					$.each( this.groups, function( name, testgroup ) {
54715						if ( testgroup === group && name !== checkElement.name ) {
54716							cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );
54717							if ( cleanElement && cleanElement.name in v.invalid ) {
54718								v.currentElements.push( cleanElement );
54719								result = v.check( cleanElement ) && result;
54720							}
54721						}
54722					} );
54723				}
54724
54725				rs = this.check( checkElement ) !== false;
54726				result = result && rs;
54727				if ( rs ) {
54728					this.invalid[ checkElement.name ] = false;
54729				} else {
54730					this.invalid[ checkElement.name ] = true;
54731				}
54732
54733				if ( !this.numberOfInvalids() ) {
54734
54735					// Hide error containers on last error
54736					this.toHide = this.toHide.add( this.containers );
54737				}
54738				this.showErrors();
54739
54740				// Add aria-invalid status for screen readers
54741				$( element ).attr( "aria-invalid", !rs );
54742			}
54743
54744			return result;
54745		},
54746
54747		// https://jqueryvalidation.org/Validator.showErrors/
54748		showErrors: function( errors ) {
54749			if ( errors ) {
54750				var validator = this;
54751
54752				// Add items to error list and map
54753				$.extend( this.errorMap, errors );
54754				this.errorList = $.map( this.errorMap, function( message, name ) {
54755					return {
54756						message: message,
54757						element: validator.findByName( name )[ 0 ]
54758					};
54759				} );
54760
54761				// Remove items from success list
54762				this.successList = $.grep( this.successList, function( element ) {
54763					return !( element.name in errors );
54764				} );
54765			}
54766			if ( this.settings.showErrors ) {
54767				this.settings.showErrors.call( this, this.errorMap, this.errorList );
54768			} else {
54769				this.defaultShowErrors();
54770			}
54771		},
54772
54773		// https://jqueryvalidation.org/Validator.resetForm/
54774		resetForm: function() {
54775			if ( $.fn.resetForm ) {
54776				$( this.currentForm ).resetForm();
54777			}
54778			this.invalid = {};
54779			this.submitted = {};
54780			this.prepareForm();
54781			this.hideErrors();
54782			var elements = this.elements()
54783				.removeData( "previousValue" )
54784				.removeAttr( "aria-invalid" );
54785
54786			this.resetElements( elements );
54787		},
54788
54789		resetElements: function( elements ) {
54790			var i;
54791
54792			if ( this.settings.unhighlight ) {
54793				for ( i = 0; elements[ i ]; i++ ) {
54794					this.settings.unhighlight.call( this, elements[ i ],
54795						this.settings.errorClass, "" );
54796					this.findByName( elements[ i ].name ).removeClass( this.settings.validClass );
54797				}
54798			} else {
54799				elements
54800					.removeClass( this.settings.errorClass )
54801					.removeClass( this.settings.validClass );
54802			}
54803		},
54804
54805		numberOfInvalids: function() {
54806			return this.objectLength( this.invalid );
54807		},
54808
54809		objectLength: function( obj ) {
54810			/* jshint unused: false */
54811			var count = 0,
54812				i;
54813			for ( i in obj ) {
54814
54815				// This check allows counting elements with empty error
54816				// message as invalid elements
54817				if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {
54818					count++;
54819				}
54820			}
54821			return count;
54822		},
54823
54824		hideErrors: function() {
54825			this.hideThese( this.toHide );
54826		},
54827
54828		hideThese: function( errors ) {
54829			errors.not( this.containers ).text( "" );
54830			this.addWrapper( errors ).hide();
54831		},
54832
54833		valid: function() {
54834			return this.size() === 0;
54835		},
54836
54837		size: function() {
54838			return this.errorList.length;
54839		},
54840
54841		focusInvalid: function() {
54842			if ( this.settings.focusInvalid ) {
54843				try {
54844					$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )
54845					.filter( ":visible" )
54846					.focus()
54847
54848					// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
54849					.trigger( "focusin" );
54850				} catch ( e ) {
54851
54852					// Ignore IE throwing errors when focusing hidden elements
54853				}
54854			}
54855		},
54856
54857		findLastActive: function() {
54858			var lastActive = this.lastActive;
54859			return lastActive && $.grep( this.errorList, function( n ) {
54860				return n.element.name === lastActive.name;
54861			} ).length === 1 && lastActive;
54862		},
54863
54864		elements: function() {
54865			var validator = this,
54866				rulesCache = {};
54867
54868			// Select all valid inputs inside the form (no submit or reset buttons)
54869			return $( this.currentForm )
54870			.find( "input, select, textarea, [contenteditable]" )
54871			.not( ":submit, :reset, :image, :disabled" )
54872			.not( this.settings.ignore )
54873			.filter( function() {
54874				var name = this.name || $( this ).attr( "name" ); // For contenteditable
54875				var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
54876
54877				if ( !name && validator.settings.debug && window.console ) {
54878					console.error( "%o has no name assigned", this );
54879				}
54880
54881				// Set form expando on contenteditable
54882				if ( isContentEditable ) {
54883					this.form = $( this ).closest( "form" )[ 0 ];
54884					this.name = name;
54885				}
54886
54887				// Ignore elements that belong to other/nested forms
54888				if ( this.form !== validator.currentForm ) {
54889					return false;
54890				}
54891
54892				// Select only the first element for each name, and only those with rules specified
54893				if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
54894					return false;
54895				}
54896
54897				rulesCache[ name ] = true;
54898				return true;
54899			} );
54900		},
54901
54902		clean: function( selector ) {
54903			return $( selector )[ 0 ];
54904		},
54905
54906		errors: function() {
54907			var errorClass = this.settings.errorClass.split( " " ).join( "." );
54908			return $( this.settings.errorElement + "." + errorClass, this.errorContext );
54909		},
54910
54911		resetInternals: function() {
54912			this.successList = [];
54913			this.errorList = [];
54914			this.errorMap = {};
54915			this.toShow = $( [] );
54916			this.toHide = $( [] );
54917		},
54918
54919		reset: function() {
54920			this.resetInternals();
54921			this.currentElements = $( [] );
54922		},
54923
54924		prepareForm: function() {
54925			this.reset();
54926			this.toHide = this.errors().add( this.containers );
54927		},
54928
54929		prepareElement: function( element ) {
54930			this.reset();
54931			this.toHide = this.errorsFor( element );
54932		},
54933
54934		elementValue: function( element ) {
54935			var $element = $( element ),
54936				type = element.type,
54937				isContentEditable = typeof $element.attr( "contenteditable" ) !== "undefined" && $element.attr( "contenteditable" ) !== "false",
54938				val, idx;
54939
54940			if ( type === "radio" || type === "checkbox" ) {
54941				return this.findByName( element.name ).filter( ":checked" ).val();
54942			} else if ( type === "number" && typeof element.validity !== "undefined" ) {
54943				return element.validity.badInput ? "NaN" : $element.val();
54944			}
54945
54946			if ( isContentEditable ) {
54947				val = $element.text();
54948			} else {
54949				val = $element.val();
54950			}
54951
54952			if ( type === "file" ) {
54953
54954				// Modern browser (chrome & safari)
54955				if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) {
54956					return val.substr( 12 );
54957				}
54958
54959				// Legacy browsers
54960				// Unix-based path
54961				idx = val.lastIndexOf( "/" );
54962				if ( idx >= 0 ) {
54963					return val.substr( idx + 1 );
54964				}
54965
54966				// Windows-based path
54967				idx = val.lastIndexOf( "\\" );
54968				if ( idx >= 0 ) {
54969					return val.substr( idx + 1 );
54970				}
54971
54972				// Just the file name
54973				return val;
54974			}
54975
54976			if ( typeof val === "string" ) {
54977				return val.replace( /\r/g, "" );
54978			}
54979			return val;
54980		},
54981
54982		check: function( element ) {
54983			element = this.validationTargetFor( this.clean( element ) );
54984
54985			var rules = $( element ).rules(),
54986				rulesCount = $.map( rules, function( n, i ) {
54987					return i;
54988				} ).length,
54989				dependencyMismatch = false,
54990				val = this.elementValue( element ),
54991				result, method, rule, normalizer;
54992
54993			// Prioritize the local normalizer defined for this element over the global one
54994			// if the former exists, otherwise user the global one in case it exists.
54995			if ( typeof rules.normalizer === "function" ) {
54996				normalizer = rules.normalizer;
54997			} else if (	typeof this.settings.normalizer === "function" ) {
54998				normalizer = this.settings.normalizer;
54999			}
55000
55001			// If normalizer is defined, then call it to retreive the changed value instead
55002			// of using the real one.
55003			// Note that `this` in the normalizer is `element`.
55004			if ( normalizer ) {
55005				val = normalizer.call( element, val );
55006
55007				// Delete the normalizer from rules to avoid treating it as a pre-defined method.
55008				delete rules.normalizer;
55009			}
55010
55011			for ( method in rules ) {
55012				rule = { method: method, parameters: rules[ method ] };
55013				try {
55014					result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
55015
55016					// If a method indicates that the field is optional and therefore valid,
55017					// don't mark it as valid when there are no other rules
55018					if ( result === "dependency-mismatch" && rulesCount === 1 ) {
55019						dependencyMismatch = true;
55020						continue;
55021					}
55022					dependencyMismatch = false;
55023
55024					if ( result === "pending" ) {
55025						this.toHide = this.toHide.not( this.errorsFor( element ) );
55026						return;
55027					}
55028
55029					if ( !result ) {
55030						this.formatAndAdd( element, rule );
55031						return false;
55032					}
55033				} catch ( e ) {
55034					if ( this.settings.debug && window.console ) {
55035						console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
55036					}
55037					if ( e instanceof TypeError ) {
55038						e.message += ".  Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
55039					}
55040
55041					throw e;
55042				}
55043			}
55044			if ( dependencyMismatch ) {
55045				return;
55046			}
55047			if ( this.objectLength( rules ) ) {
55048				this.successList.push( element );
55049			}
55050			return true;
55051		},
55052
55053		// Return the custom message for the given element and validation method
55054		// specified in the element's HTML5 data attribute
55055		// return the generic message if present and no method specific message is present
55056		customDataMessage: function( element, method ) {
55057			return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
55058				method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
55059		},
55060
55061		// Return the custom message for the given element name and validation method
55062		customMessage: function( name, method ) {
55063			var m = this.settings.messages[ name ];
55064			return m && ( m.constructor === String ? m : m[ method ] );
55065		},
55066
55067		// Return the first defined argument, allowing empty strings
55068		findDefined: function() {
55069			for ( var i = 0; i < arguments.length; i++ ) {
55070				if ( arguments[ i ] !== undefined ) {
55071					return arguments[ i ];
55072				}
55073			}
55074			return undefined;
55075		},
55076
55077		// The second parameter 'rule' used to be a string, and extended to an object literal
55078		// of the following form:
55079		// rule = {
55080		//     method: "method name",
55081		//     parameters: "the given method parameters"
55082		// }
55083		//
55084		// The old behavior still supported, kept to maintain backward compatibility with
55085		// old code, and will be removed in the next major release.
55086		defaultMessage: function( element, rule ) {
55087			if ( typeof rule === "string" ) {
55088				rule = { method: rule };
55089			}
55090
55091			var message = this.findDefined(
55092					this.customMessage( element.name, rule.method ),
55093					this.customDataMessage( element, rule.method ),
55094
55095					// 'title' is never undefined, so handle empty string as undefined
55096					!this.settings.ignoreTitle && element.title || undefined,
55097					$.validator.messages[ rule.method ],
55098					"<strong>Warning: No message defined for " + element.name + "</strong>"
55099				),
55100				theregex = /\$?\{(\d+)\}/g;
55101			if ( typeof message === "function" ) {
55102				message = message.call( this, rule.parameters, element );
55103			} else if ( theregex.test( message ) ) {
55104				message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
55105			}
55106
55107			return message;
55108		},
55109
55110		formatAndAdd: function( element, rule ) {
55111			var message = this.defaultMessage( element, rule );
55112
55113			this.errorList.push( {
55114				message: message,
55115				element: element,
55116				method: rule.method
55117			} );
55118
55119			this.errorMap[ element.name ] = message;
55120			this.submitted[ element.name ] = message;
55121		},
55122
55123		addWrapper: function( toToggle ) {
55124			if ( this.settings.wrapper ) {
55125				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
55126			}
55127			return toToggle;
55128		},
55129
55130		defaultShowErrors: function() {
55131			var i, elements, error;
55132			for ( i = 0; this.errorList[ i ]; i++ ) {
55133				error = this.errorList[ i ];
55134				if ( this.settings.highlight ) {
55135					this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
55136				}
55137				this.showLabel( error.element, error.message );
55138			}
55139			if ( this.errorList.length ) {
55140				this.toShow = this.toShow.add( this.containers );
55141			}
55142			if ( this.settings.success ) {
55143				for ( i = 0; this.successList[ i ]; i++ ) {
55144					this.showLabel( this.successList[ i ] );
55145				}
55146			}
55147			if ( this.settings.unhighlight ) {
55148				for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
55149					this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
55150				}
55151			}
55152			this.toHide = this.toHide.not( this.toShow );
55153			this.hideErrors();
55154			this.addWrapper( this.toShow ).show();
55155		},
55156
55157		validElements: function() {
55158			return this.currentElements.not( this.invalidElements() );
55159		},
55160
55161		invalidElements: function() {
55162			return $( this.errorList ).map( function() {
55163				return this.element;
55164			} );
55165		},
55166
55167		showLabel: function( element, message ) {
55168			var place, group, errorID, v,
55169				error = this.errorsFor( element ),
55170				elementID = this.idOrName( element ),
55171				describedBy = $( element ).attr( "aria-describedby" );
55172
55173			if ( error.length ) {
55174
55175				// Refresh error/success class
55176				error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
55177
55178				// Replace message on existing label
55179				error.html( message );
55180			} else {
55181
55182				// Create error element
55183				error = $( "<" + this.settings.errorElement + ">" )
55184					.attr( "id", elementID + "-error" )
55185					.addClass( this.settings.errorClass )
55186					.html( message || "" );
55187
55188				// Maintain reference to the element to be placed into the DOM
55189				place = error;
55190				if ( this.settings.wrapper ) {
55191
55192					// Make sure the element is visible, even in IE
55193					// actually showing the wrapped element is handled elsewhere
55194					place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
55195				}
55196				if ( this.labelContainer.length ) {
55197					this.labelContainer.append( place );
55198				} else if ( this.settings.errorPlacement ) {
55199					this.settings.errorPlacement.call( this, place, $( element ) );
55200				} else {
55201					place.insertAfter( element );
55202				}
55203
55204				// Link error back to the element
55205				if ( error.is( "label" ) ) {
55206
55207					// If the error is a label, then associate using 'for'
55208					error.attr( "for", elementID );
55209
55210					// If the element is not a child of an associated label, then it's necessary
55211					// to explicitly apply aria-describedby
55212				} else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) {
55213					errorID = error.attr( "id" );
55214
55215					// Respect existing non-error aria-describedby
55216					if ( !describedBy ) {
55217						describedBy = errorID;
55218					} else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) {
55219
55220						// Add to end of list if not already present
55221						describedBy += " " + errorID;
55222					}
55223					$( element ).attr( "aria-describedby", describedBy );
55224
55225					// If this element is grouped, then assign to all elements in the same group
55226					group = this.groups[ element.name ];
55227					if ( group ) {
55228						v = this;
55229						$.each( v.groups, function( name, testgroup ) {
55230							if ( testgroup === group ) {
55231								$( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm )
55232									.attr( "aria-describedby", error.attr( "id" ) );
55233							}
55234						} );
55235					}
55236				}
55237			}
55238			if ( !message && this.settings.success ) {
55239				error.text( "" );
55240				if ( typeof this.settings.success === "string" ) {
55241					error.addClass( this.settings.success );
55242				} else {
55243					this.settings.success( error, element );
55244				}
55245			}
55246			this.toShow = this.toShow.add( error );
55247		},
55248
55249		errorsFor: function( element ) {
55250			var name = this.escapeCssMeta( this.idOrName( element ) ),
55251				describer = $( element ).attr( "aria-describedby" ),
55252				selector = "label[for='" + name + "'], label[for='" + name + "'] *";
55253
55254			// 'aria-describedby' should directly reference the error element
55255			if ( describer ) {
55256				selector = selector + ", #" + this.escapeCssMeta( describer )
55257					.replace( /\s+/g, ", #" );
55258			}
55259
55260			return this
55261				.errors()
55262				.filter( selector );
55263		},
55264
55265		// See https://api.jquery.com/category/selectors/, for CSS
55266		// meta-characters that should be escaped in order to be used with JQuery
55267		// as a literal part of a name/id or any selector.
55268		escapeCssMeta: function( string ) {
55269			return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" );
55270		},
55271
55272		idOrName: function( element ) {
55273			return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
55274		},
55275
55276		validationTargetFor: function( element ) {
55277
55278			// If radio/checkbox, validate first element in group instead
55279			if ( this.checkable( element ) ) {
55280				element = this.findByName( element.name );
55281			}
55282
55283			// Always apply ignore filter
55284			return $( element ).not( this.settings.ignore )[ 0 ];
55285		},
55286
55287		checkable: function( element ) {
55288			return ( /radio|checkbox/i ).test( element.type );
55289		},
55290
55291		findByName: function( name ) {
55292			return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" );
55293		},
55294
55295		getLength: function( value, element ) {
55296			switch ( element.nodeName.toLowerCase() ) {
55297			case "select":
55298				return $( "option:selected", element ).length;
55299			case "input":
55300				if ( this.checkable( element ) ) {
55301					return this.findByName( element.name ).filter( ":checked" ).length;
55302				}
55303			}
55304			return value.length;
55305		},
55306
55307		depend: function( param, element ) {
55308			return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;
55309		},
55310
55311		dependTypes: {
55312			"boolean": function( param ) {
55313				return param;
55314			},
55315			"string": function( param, element ) {
55316				return !!$( param, element.form ).length;
55317			},
55318			"function": function( param, element ) {
55319				return param( element );
55320			}
55321		},
55322
55323		optional: function( element ) {
55324			var val = this.elementValue( element );
55325			return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
55326		},
55327
55328		startRequest: function( element ) {
55329			if ( !this.pending[ element.name ] ) {
55330				this.pendingRequest++;
55331				$( element ).addClass( this.settings.pendingClass );
55332				this.pending[ element.name ] = true;
55333			}
55334		},
55335
55336		stopRequest: function( element, valid ) {
55337			this.pendingRequest--;
55338
55339			// Sometimes synchronization fails, make sure pendingRequest is never < 0
55340			if ( this.pendingRequest < 0 ) {
55341				this.pendingRequest = 0;
55342			}
55343			delete this.pending[ element.name ];
55344			$( element ).removeClass( this.settings.pendingClass );
55345			if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
55346				$( this.currentForm ).submit();
55347
55348				// Remove the hidden input that was used as a replacement for the
55349				// missing submit button. The hidden input is added by `handle()`
55350				// to ensure that the value of the used submit button is passed on
55351				// for scripted submits triggered by this method
55352				if ( this.submitButton ) {
55353					$( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove();
55354				}
55355
55356				this.formSubmitted = false;
55357			} else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {
55358				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
55359				this.formSubmitted = false;
55360			}
55361		},
55362
55363		previousValue: function( element, method ) {
55364			method = typeof method === "string" && method || "remote";
55365
55366			return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
55367				old: null,
55368				valid: true,
55369				message: this.defaultMessage( element, { method: method } )
55370			} );
55371		},
55372
55373		// Cleans up all forms and elements, removes validator-specific events
55374		destroy: function() {
55375			this.resetForm();
55376
55377			$( this.currentForm )
55378				.off( ".validate" )
55379				.removeData( "validator" )
55380				.find( ".validate-equalTo-blur" )
55381					.off( ".validate-equalTo" )
55382					.removeClass( "validate-equalTo-blur" )
55383				.find( ".validate-lessThan-blur" )
55384					.off( ".validate-lessThan" )
55385					.removeClass( "validate-lessThan-blur" )
55386				.find( ".validate-lessThanEqual-blur" )
55387					.off( ".validate-lessThanEqual" )
55388					.removeClass( "validate-lessThanEqual-blur" )
55389				.find( ".validate-greaterThanEqual-blur" )
55390					.off( ".validate-greaterThanEqual" )
55391					.removeClass( "validate-greaterThanEqual-blur" )
55392				.find( ".validate-greaterThan-blur" )
55393					.off( ".validate-greaterThan" )
55394					.removeClass( "validate-greaterThan-blur" );
55395		}
55396
55397	},
55398
55399	classRuleSettings: {
55400		required: { required: true },
55401		email: { email: true },
55402		url: { url: true },
55403		date: { date: true },
55404		dateISO: { dateISO: true },
55405		number: { number: true },
55406		digits: { digits: true },
55407		creditcard: { creditcard: true }
55408	},
55409
55410	addClassRules: function( className, rules ) {
55411		if ( className.constructor === String ) {
55412			this.classRuleSettings[ className ] = rules;
55413		} else {
55414			$.extend( this.classRuleSettings, className );
55415		}
55416	},
55417
55418	classRules: function( element ) {
55419		var rules = {},
55420			classes = $( element ).attr( "class" );
55421
55422		if ( classes ) {
55423			$.each( classes.split( " " ), function() {
55424				if ( this in $.validator.classRuleSettings ) {
55425					$.extend( rules, $.validator.classRuleSettings[ this ] );
55426				}
55427			} );
55428		}
55429		return rules;
55430	},
55431
55432	normalizeAttributeRule: function( rules, type, method, value ) {
55433
55434		// Convert the value to a number for number inputs, and for text for backwards compability
55435		// allows type="date" and others to be compared as strings
55436		if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
55437			value = Number( value );
55438
55439			// Support Opera Mini, which returns NaN for undefined minlength
55440			if ( isNaN( value ) ) {
55441				value = undefined;
55442			}
55443		}
55444
55445		if ( value || value === 0 ) {
55446			rules[ method ] = value;
55447		} else if ( type === method && type !== "range" ) {
55448
55449			// Exception: the jquery validate 'range' method
55450			// does not test for the html5 'range' type
55451			rules[ method ] = true;
55452		}
55453	},
55454
55455	attributeRules: function( element ) {
55456		var rules = {},
55457			$element = $( element ),
55458			type = element.getAttribute( "type" ),
55459			method, value;
55460
55461		for ( method in $.validator.methods ) {
55462
55463			// Support for <input required> in both html5 and older browsers
55464			if ( method === "required" ) {
55465				value = element.getAttribute( method );
55466
55467				// Some browsers return an empty string for the required attribute
55468				// and non-HTML5 browsers might have required="" markup
55469				if ( value === "" ) {
55470					value = true;
55471				}
55472
55473				// Force non-HTML5 browsers to return bool
55474				value = !!value;
55475			} else {
55476				value = $element.attr( method );
55477			}
55478
55479			this.normalizeAttributeRule( rules, type, method, value );
55480		}
55481
55482		// 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
55483		if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
55484			delete rules.maxlength;
55485		}
55486
55487		return rules;
55488	},
55489
55490	dataRules: function( element ) {
55491		var rules = {},
55492			$element = $( element ),
55493			type = element.getAttribute( "type" ),
55494			method, value;
55495
55496		for ( method in $.validator.methods ) {
55497			value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
55498
55499			// Cast empty attributes like `data-rule-required` to `true`
55500			if ( value === "" ) {
55501				value = true;
55502			}
55503
55504			this.normalizeAttributeRule( rules, type, method, value );
55505		}
55506		return rules;
55507	},
55508
55509	staticRules: function( element ) {
55510		var rules = {},
55511			validator = $.data( element.form, "validator" );
55512
55513		if ( validator.settings.rules ) {
55514			rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
55515		}
55516		return rules;
55517	},
55518
55519	normalizeRules: function( rules, element ) {
55520
55521		// Handle dependency check
55522		$.each( rules, function( prop, val ) {
55523
55524			// Ignore rule when param is explicitly false, eg. required:false
55525			if ( val === false ) {
55526				delete rules[ prop ];
55527				return;
55528			}
55529			if ( val.param || val.depends ) {
55530				var keepRule = true;
55531				switch ( typeof val.depends ) {
55532				case "string":
55533					keepRule = !!$( val.depends, element.form ).length;
55534					break;
55535				case "function":
55536					keepRule = val.depends.call( element, element );
55537					break;
55538				}
55539				if ( keepRule ) {
55540					rules[ prop ] = val.param !== undefined ? val.param : true;
55541				} else {
55542					$.data( element.form, "validator" ).resetElements( $( element ) );
55543					delete rules[ prop ];
55544				}
55545			}
55546		} );
55547
55548		// Evaluate parameters
55549		$.each( rules, function( rule, parameter ) {
55550			rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter;
55551		} );
55552
55553		// Clean number parameters
55554		$.each( [ "minlength", "maxlength" ], function() {
55555			if ( rules[ this ] ) {
55556				rules[ this ] = Number( rules[ this ] );
55557			}
55558		} );
55559		$.each( [ "rangelength", "range" ], function() {
55560			var parts;
55561			if ( rules[ this ] ) {
55562				if ( $.isArray( rules[ this ] ) ) {
55563					rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];
55564				} else if ( typeof rules[ this ] === "string" ) {
55565					parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ );
55566					rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];
55567				}
55568			}
55569		} );
55570
55571		if ( $.validator.autoCreateRanges ) {
55572
55573			// Auto-create ranges
55574			if ( rules.min != null && rules.max != null ) {
55575				rules.range = [ rules.min, rules.max ];
55576				delete rules.min;
55577				delete rules.max;
55578			}
55579			if ( rules.minlength != null && rules.maxlength != null ) {
55580				rules.rangelength = [ rules.minlength, rules.maxlength ];
55581				delete rules.minlength;
55582				delete rules.maxlength;
55583			}
55584		}
55585
55586		return rules;
55587	},
55588
55589	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
55590	normalizeRule: function( data ) {
55591		if ( typeof data === "string" ) {
55592			var transformed = {};
55593			$.each( data.split( /\s/ ), function() {
55594				transformed[ this ] = true;
55595			} );
55596			data = transformed;
55597		}
55598		return data;
55599	},
55600
55601	// https://jqueryvalidation.org/jQuery.validator.addMethod/
55602	addMethod: function( name, method, message ) {
55603		$.validator.methods[ name ] = method;
55604		$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
55605		if ( method.length < 3 ) {
55606			$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
55607		}
55608	},
55609
55610	// https://jqueryvalidation.org/jQuery.validator.methods/
55611	methods: {
55612
55613		// https://jqueryvalidation.org/required-method/
55614		required: function( value, element, param ) {
55615
55616			// Check if dependency is met
55617			if ( !this.depend( param, element ) ) {
55618				return "dependency-mismatch";
55619			}
55620			if ( element.nodeName.toLowerCase() === "select" ) {
55621
55622				// Could be an array for select-multiple or a string, both are fine this way
55623				var val = $( element ).val();
55624				return val && val.length > 0;
55625			}
55626			if ( this.checkable( element ) ) {
55627				return this.getLength( value, element ) > 0;
55628			}
55629			return value !== undefined && value !== null && value.length > 0;
55630		},
55631
55632		// https://jqueryvalidation.org/email-method/
55633		email: function( value, element ) {
55634
55635			// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
55636			// Retrieved 2014-01-14
55637			// If you have a problem with this implementation, report a bug against the above spec
55638			// Or use custom methods to implement your own email validation
55639			return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
55640		},
55641
55642		// https://jqueryvalidation.org/url-method/
55643		url: function( value, element ) {
55644
55645			// Copyright (c) 2010-2013 Diego Perini, MIT licensed
55646			// https://gist.github.com/dperini/729294
55647			// see also https://mathiasbynens.be/demo/url-regex
55648			// modified to allow protocol-relative URLs
55649			return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
55650		},
55651
55652		// https://jqueryvalidation.org/date-method/
55653		date: ( function() {
55654			var called = false;
55655
55656			return function( value, element ) {
55657				if ( !called ) {
55658					called = true;
55659					if ( this.settings.debug && window.console ) {
55660						console.warn(
55661							"The `date` method is deprecated and will be removed in version '2.0.0'.\n" +
55662							"Please don't use it, since it relies on the Date constructor, which\n" +
55663							"behaves very differently across browsers and locales. Use `dateISO`\n" +
55664							"instead or one of the locale specific methods in `localizations/`\n" +
55665							"and `additional-methods.js`."
55666						);
55667					}
55668				}
55669
55670				return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
55671			};
55672		}() ),
55673
55674		// https://jqueryvalidation.org/dateISO-method/
55675		dateISO: function( value, element ) {
55676			return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
55677		},
55678
55679		// https://jqueryvalidation.org/number-method/
55680		number: function( value, element ) {
55681			return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
55682		},
55683
55684		// https://jqueryvalidation.org/digits-method/
55685		digits: function( value, element ) {
55686			return this.optional( element ) || /^\d+$/.test( value );
55687		},
55688
55689		// https://jqueryvalidation.org/minlength-method/
55690		minlength: function( value, element, param ) {
55691			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
55692			return this.optional( element ) || length >= param;
55693		},
55694
55695		// https://jqueryvalidation.org/maxlength-method/
55696		maxlength: function( value, element, param ) {
55697			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
55698			return this.optional( element ) || length <= param;
55699		},
55700
55701		// https://jqueryvalidation.org/rangelength-method/
55702		rangelength: function( value, element, param ) {
55703			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
55704			return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
55705		},
55706
55707		// https://jqueryvalidation.org/min-method/
55708		min: function( value, element, param ) {
55709			return this.optional( element ) || value >= param;
55710		},
55711
55712		// https://jqueryvalidation.org/max-method/
55713		max: function( value, element, param ) {
55714			return this.optional( element ) || value <= param;
55715		},
55716
55717		// https://jqueryvalidation.org/range-method/
55718		range: function( value, element, param ) {
55719			return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
55720		},
55721
55722		// https://jqueryvalidation.org/step-method/
55723		step: function( value, element, param ) {
55724			var type = $( element ).attr( "type" ),
55725				errorMessage = "Step attribute on input type " + type + " is not supported.",
55726				supportedTypes = [ "text", "number", "range" ],
55727				re = new RegExp( "\\b" + type + "\\b" ),
55728				notSupported = type && !re.test( supportedTypes.join() ),
55729				decimalPlaces = function( num ) {
55730					var match = ( "" + num ).match( /(?:\.(\d+))?$/ );
55731					if ( !match ) {
55732						return 0;
55733					}
55734
55735					// Number of digits right of decimal point.
55736					return match[ 1 ] ? match[ 1 ].length : 0;
55737				},
55738				toInt = function( num ) {
55739					return Math.round( num * Math.pow( 10, decimals ) );
55740				},
55741				valid = true,
55742				decimals;
55743
55744			// Works only for text, number and range input types
55745			// TODO find a way to support input types date, datetime, datetime-local, month, time and week
55746			if ( notSupported ) {
55747				throw new Error( errorMessage );
55748			}
55749
55750			decimals = decimalPlaces( param );
55751
55752			// Value can't have too many decimals
55753			if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {
55754				valid = false;
55755			}
55756
55757			return this.optional( element ) || valid;
55758		},
55759
55760		// https://jqueryvalidation.org/equalTo-method/
55761		equalTo: function( value, element, param ) {
55762
55763			// Bind to the blur event of the target in order to revalidate whenever the target field is updated
55764			var target = $( param );
55765			if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
55766				target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
55767					$( element ).valid();
55768				} );
55769			}
55770			return value === target.val();
55771		},
55772
55773		// https://jqueryvalidation.org/remote-method/
55774		remote: function( value, element, param, method ) {
55775			if ( this.optional( element ) ) {
55776				return "dependency-mismatch";
55777			}
55778
55779			method = typeof method === "string" && method || "remote";
55780
55781			var previous = this.previousValue( element, method ),
55782				validator, data, optionDataString;
55783
55784			if ( !this.settings.messages[ element.name ] ) {
55785				this.settings.messages[ element.name ] = {};
55786			}
55787			previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];
55788			this.settings.messages[ element.name ][ method ] = previous.message;
55789
55790			param = typeof param === "string" && { url: param } || param;
55791			optionDataString = $.param( $.extend( { data: value }, param.data ) );
55792			if ( previous.old === optionDataString ) {
55793				return previous.valid;
55794			}
55795
55796			previous.old = optionDataString;
55797			validator = this;
55798			this.startRequest( element );
55799			data = {};
55800			data[ element.name ] = value;
55801			$.ajax( $.extend( true, {
55802				mode: "abort",
55803				port: "validate" + element.name,
55804				dataType: "json",
55805				data: data,
55806				context: validator.currentForm,
55807				success: function( response ) {
55808					var valid = response === true || response === "true",
55809						errors, message, submitted;
55810
55811					validator.settings.messages[ element.name ][ method ] = previous.originalMessage;
55812					if ( valid ) {
55813						submitted = validator.formSubmitted;
55814						validator.resetInternals();
55815						validator.toHide = validator.errorsFor( element );
55816						validator.formSubmitted = submitted;
55817						validator.successList.push( element );
55818						validator.invalid[ element.name ] = false;
55819						validator.showErrors();
55820					} else {
55821						errors = {};
55822						message = response || validator.defaultMessage( element, { method: method, parameters: value } );
55823						errors[ element.name ] = previous.message = message;
55824						validator.invalid[ element.name ] = true;
55825						validator.showErrors( errors );
55826					}
55827					previous.valid = valid;
55828					validator.stopRequest( element, valid );
55829				}
55830			}, param ) );
55831			return "pending";
55832		}
55833	}
55834
55835} );
55836
55837// Ajax mode: abort
55838// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
55839// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
55840
55841var pendingRequests = {},
55842	ajax;
55843
55844// Use a prefilter if available (1.5+)
55845if ( $.ajaxPrefilter ) {
55846	$.ajaxPrefilter( function( settings, _, xhr ) {
55847		var port = settings.port;
55848		if ( settings.mode === "abort" ) {
55849			if ( pendingRequests[ port ] ) {
55850				pendingRequests[ port ].abort();
55851			}
55852			pendingRequests[ port ] = xhr;
55853		}
55854	} );
55855} else {
55856
55857	// Proxy ajax
55858	ajax = $.ajax;
55859	$.ajax = function( settings ) {
55860		var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
55861			port = ( "port" in settings ? settings : $.ajaxSettings ).port;
55862		if ( mode === "abort" ) {
55863			if ( pendingRequests[ port ] ) {
55864				pendingRequests[ port ].abort();
55865			}
55866			pendingRequests[ port ] = ajax.apply( this, arguments );
55867			return pendingRequests[ port ];
55868		}
55869		return ajax.apply( this, arguments );
55870	};
55871}
55872return $;
55873}));
55874/*!
55875 * jQuery Validation Plugin v1.19.0
55876 *
55877 * https://jqueryvalidation.org/
55878 *
55879 * Copyright (c) 2018 Jörn Zaefferer
55880 * Released under the MIT license
55881 */
55882(function( factory ) {
55883	if ( typeof define === "function" && define.amd ) {
55884		define( ["jquery", "./jquery.validate"], factory );
55885	} else if (typeof module === "object" && module.exports) {
55886		module.exports = factory( require( "jquery" ) );
55887	} else {
55888		factory( jQuery );
55889	}
55890}(function( $ ) {
55891
55892( function() {
55893
55894	function stripHtml( value ) {
55895
55896		// Remove html tags and space chars
55897		return value.replace( /<.[^<>]*?>/g, " " ).replace( /&nbsp;|&#160;/gi, " " )
55898
55899		// Remove punctuation
55900		.replace( /[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "" );
55901	}
55902
55903	$.validator.addMethod( "maxWords", function( value, element, params ) {
vendor: 4,581 bytes, lines 55904-56036
55904		return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length <= params;
55905	}, $.validator.format( "Please enter {0} words or less." ) );
55906
55907	$.validator.addMethod( "minWords", function( value, element, params ) {
55908		return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length >= params;
55909	}, $.validator.format( "Please enter at least {0} words." ) );
55910
55911	$.validator.addMethod( "rangeWords", function( value, element, params ) {
55912		var valueStripped = stripHtml( value ),
55913			regex = /\b\w+\b/g;
55914		return this.optional( element ) || valueStripped.match( regex ).length >= params[ 0 ] && valueStripped.match( regex ).length <= params[ 1 ];
55915	}, $.validator.format( "Please enter between {0} and {1} words." ) );
55916
55917}() );
55918
55919/**
55920 * This is used in the United States to process payments, deposits,
55921 * or transfers using the Automated Clearing House (ACH) or Fedwire
55922 * systems. A very common use case would be to validate a form for
55923 * an ACH bill payment.
55924 */
55925$.validator.addMethod( "abaRoutingNumber", function( value ) {
55926	var checksum = 0;
55927	var tokens = value.split( "" );
55928	var length = tokens.length;
55929
55930	// Length Check
55931	if ( length !== 9 ) {
55932		return false;
55933	}
55934
55935	// Calc the checksum
55936	// https://en.wikipedia.org/wiki/ABA_routing_transit_number
55937	for ( var i = 0; i < length; i += 3 ) {
55938		checksum +=	parseInt( tokens[ i ], 10 )     * 3 +
55939					parseInt( tokens[ i + 1 ], 10 ) * 7 +
55940					parseInt( tokens[ i + 2 ], 10 );
55941	}
55942
55943	// If not zero and divisible by 10 then valid
55944	if ( checksum !== 0 && checksum % 10 === 0 ) {
55945		return true;
55946	}
55947
55948	return false;
55949}, "Please enter a valid routing number." );
55950
55951// Accept a value from a file input based on a required mimetype
55952$.validator.addMethod( "accept", function( value, element, param ) {
55953
55954	// Split mime on commas in case we have multiple types we can accept
55955	var typeParam = typeof param === "string" ? param.replace( /\s/g, "" ) : "image/*",
55956		optionalValue = this.optional( element ),
55957		i, file, regex;
55958
55959	// Element is optional
55960	if ( optionalValue ) {
55961		return optionalValue;
55962	}
55963
55964	if ( $( element ).attr( "type" ) === "file" ) {
55965
55966		// Escape string to be used in the regex
55967		// see: https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
55968		// Escape also "/*" as "/.*" as a wildcard
55969		typeParam = typeParam
55970				.replace( /[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, "\\$&" )
55971				.replace( /,/g, "|" )
55972				.replace( /\/\*/g, "/.*" );
55973
55974		// Check if the element has a FileList before checking each file
55975		if ( element.files && element.files.length ) {
55976			regex = new RegExp( ".?(" + typeParam + ")$", "i" );
55977			for ( i = 0; i < element.files.length; i++ ) {
55978				file = element.files[ i ];
55979
55980				// Grab the mimetype from the loaded file, verify it matches
55981				if ( !file.type.match( regex ) ) {
55982					return false;
55983				}
55984			}
55985		}
55986	}
55987
55988	// Either return true because we've validated each file, or because the
55989	// browser does not support element.files and the FileList feature
55990	return true;
55991}, $.validator.format( "Please enter a value with a valid mimetype." ) );
55992
55993$.validator.addMethod( "alphanumeric", function( value, element ) {
55994	return this.optional( element ) || /^\w+$/i.test( value );
55995}, "Letters, numbers, and underscores only please" );
55996
55997/*
55998 * Dutch bank account numbers (not 'giro' numbers) have 9 digits
55999 * and pass the '11 check'.
56000 * We accept the notation with spaces, as that is common.
56001 * acceptable: 123456789 or 12 34 56 789
56002 */
56003$.validator.addMethod( "bankaccountNL", function( value, element ) {
56004	if ( this.optional( element ) ) {
56005		return true;
56006	}
56007	if ( !( /^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test( value ) ) ) {
56008		return false;
56009	}
56010
56011	// Now '11 check'
56012	var account = value.replace( / /g, "" ), // Remove spaces
56013		sum = 0,
56014		len = account.length,
56015		pos, factor, digit;
56016	for ( pos = 0; pos < len; pos++ ) {
56017		factor = len - pos;
56018		digit = account.substring( pos, pos + 1 );
56019		sum = sum + factor * digit;
56020	}
56021	return sum % 11 === 0;
56022}, "Please specify a valid bank account number" );
56023
56024$.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
56025	return this.optional( element ) ||
56026			( $.validator.methods.bankaccountNL.call( this, value, element ) ) ||
56027			( $.validator.methods.giroaccountNL.call( this, value, element ) );
56028}, "Please specify a valid bank or giro account number" );
56029
56030/**
56031 * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
56032 *
56033 * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
56034 *
56035 * Validation is case-insensitive. Please make sure to normalize input yourself.
56036 *
56037 * BIC definition in detail:
56038 * - First 4 characters - bank code (only letters)
56039 * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
56040 * - Next 2 characters - location code (letters and digits)
56041 *   a. shall not start with '0' or '1'
56042 *   b. second character must be a letter ('O' is not allowed) or digit ('0' for test (therefore not allowed), '1' denoting passive participant, '2' typically reverse-billing)
56043 * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
56044 */
56045$.validator.addMethod( "bic", function( value, element ) {
56046    return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() );
56047}, "Please specify a valid BIC code" );
56048
56049/*
56050 * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
56051 * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
56052 *
56053 * Spanish CIF structure:
56054 *
56055 * [ T ][ P ][ P ][ N ][ N ][ N ][ N ][ N ][ C ]
56056 *
56057 * Where:
56058 *
56059 * T: 1 character. Kind of Organization Letter: [ABCDEFGHJKLMNPQRSUVW]
56060 * P: 2 characters. Province.
56061 * N: 5 characters. Secuencial Number within the province.
56062 * C: 1 character. Control Digit: [0-9A-J].
56063 *
56064 * [ T ]: Kind of Organizations. Possible values:
56065 *
56066 *   A. Corporations
56067 *   B. LLCs
56068 *   C. General partnerships
56069 *   D. Companies limited partnerships
56070 *   E. Communities of goods
56071 *   F. Cooperative Societies
56072 *   G. Associations
56073 *   H. Communities of homeowners in horizontal property regime
56074 *   J. Civil Societies
56075 *   K. Old format
56076 *   L. Old format
56077 *   M. Old format
56078 *   N. Nonresident entities
56079 *   P. Local authorities
56080 *   Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
56081 *   R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
56082 *   S. Organs of State Administration and regions
56083 *   V. Agrarian Transformation
56084 *   W. Permanent establishments of non-resident in Spain
56085 *
56086 * [ C ]: Control Digit. It can be a number or a letter depending on T value:
56087 * [ T ]  -->  [ C ]
56088 * ------    ----------
56089 *   A         Number
56090 *   B         Number
56091 *   E         Number
56092 *   H         Number
56093 *   K         Letter
56094 *   P         Letter
56095 *   Q         Letter
56096 *   S         Letter
56097 *
56098 */
56099$.validator.addMethod( "cifES", function( value, element ) {
56100	"use strict";
56101
56102	if ( this.optional( element ) ) {
56103		return true;
56104	}
56105
56106	var cifRegEx = new RegExp( /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/gi );
56107	var letter  = value.substring( 0, 1 ), // [ T ]
56108		number  = value.substring( 1, 8 ), // [ P ][ P ][ N ][ N ][ N ][ N ][ N ]
56109		control = value.substring( 8, 9 ), // [ C ]
56110		all_sum = 0,
56111		even_sum = 0,
56112		odd_sum = 0,
56113		i, n,
56114		control_digit,
56115		control_letter;
56116
56117	function isOdd( n ) {
56118		return n % 2 === 0;
56119	}
56120
56121	// Quick format test
56122	if ( value.length !== 9 || !cifRegEx.test( value ) ) {
56123		return false;
56124	}
56125
56126	for ( i = 0; i < number.length; i++ ) {
56127		n = parseInt( number[ i ], 10 );
56128
56129		// Odd positions
56130		if ( isOdd( i ) ) {
56131
56132			// Odd positions are multiplied first.
56133			n *= 2;
56134
56135			// If the multiplication is bigger than 10 we need to adjust
56136			odd_sum += n < 10 ? n : n - 9;
56137
56138		// Even positions
56139		// Just sum them
56140		} else {
56141			even_sum += n;
56142		}
56143	}
56144
56145	all_sum = even_sum + odd_sum;
56146	control_digit = ( 10 - ( all_sum ).toString().substr( -1 ) ).toString();
56147	control_digit = parseInt( control_digit, 10 ) > 9 ? "0" : control_digit;
56148	control_letter = "JABCDEFGHI".substr( control_digit, 1 ).toString();
56149
56150	// Control must be a digit
56151	if ( letter.match( /[ABEH]/ ) ) {
56152		return control === control_digit;
56153
56154	// Control must be a letter
56155	} else if ( letter.match( /[KPQS]/ ) ) {
56156		return control === control_letter;
56157	}
56158
56159	// Can be either
56160	return control === control_digit || control === control_letter;
56161
56162}, "Please specify a valid CIF number." );
56163
56164/*
56165 * Brazillian CNH number (Carteira Nacional de Habilitacao) is the License Driver number.
56166 * CNH numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
56167 */
56168$.validator.addMethod( "cnhBR", function( value ) {
56169
56170  // Removing special characters from value
56171  value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
56172
56173  // Checking value to have 11 digits only
56174  if ( value.length !== 11 ) {
56175    return false;
vendor: 28,001 bytes, lines 56176-57067
56176  }
56177
56178  var sum = 0, dsc = 0, firstChar,
56179		firstCN, secondCN, i, j, v;
56180
56181  firstChar = value.charAt( 0 );
56182
56183  if ( new Array( 12 ).join( firstChar ) === value ) {
56184    return false;
56185  }
56186
56187  // Step 1 - using first Check Number:
56188  for ( i = 0, j = 9, v = 0; i < 9; ++i, --j ) {
56189    sum += +( value.charAt( i ) * j );
56190  }
56191
56192  firstCN = sum % 11;
56193  if ( firstCN >= 10 ) {
56194    firstCN = 0;
56195    dsc = 2;
56196  }
56197
56198  sum = 0;
56199  for ( i = 0, j = 1, v = 0; i < 9; ++i, ++j ) {
56200    sum += +( value.charAt( i ) * j );
56201  }
56202
56203  secondCN = sum % 11;
56204  if ( secondCN >= 10 ) {
56205    secondCN = 0;
56206  } else {
56207    secondCN = secondCN - dsc;
56208  }
56209
56210  return ( String( firstCN ).concat( secondCN ) === value.substr( -2 ) );
56211
56212}, "Please specify a valid CNH number" );
56213
56214/*
56215 * Brazillian value number (Cadastrado de Pessoas Juridica).
56216 * value numbers have 14 digits in total: 12 numbers followed by 2 check numbers that are being used for validation.
56217 */
56218$.validator.addMethod( "cnpjBR", function( value, element ) {
56219	"use strict";
56220
56221	if ( this.optional( element ) ) {
56222		return true;
56223	}
56224
56225	// Removing no number
56226	value = value.replace( /[^\d]+/g, "" );
56227
56228	// Checking value to have 14 digits only
56229	if ( value.length !== 14 ) {
56230		return false;
56231	}
56232
56233	// Elimina values invalidos conhecidos
56234	if ( value === "00000000000000" ||
56235		value === "11111111111111" ||
56236		value === "22222222222222" ||
56237		value === "33333333333333" ||
56238		value === "44444444444444" ||
56239		value === "55555555555555" ||
56240		value === "66666666666666" ||
56241		value === "77777777777777" ||
56242		value === "88888888888888" ||
56243		value === "99999999999999" ) {
56244		return false;
56245	}
56246
56247	// Valida DVs
56248	var tamanho = ( value.length - 2 );
56249	var numeros = value.substring( 0, tamanho );
56250	var digitos = value.substring( tamanho );
56251	var soma = 0;
56252	var pos = tamanho - 7;
56253
56254	for ( var i = tamanho; i >= 1; i-- ) {
56255		soma += numeros.charAt( tamanho - i ) * pos--;
56256		if ( pos < 2 ) {
56257			pos = 9;
56258		}
56259	}
56260
56261	var resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
56262
56263	if ( resultado !== parseInt( digitos.charAt( 0 ), 10 ) ) {
56264		return false;
56265	}
56266
56267	tamanho = tamanho + 1;
56268	numeros = value.substring( 0, tamanho );
56269	soma = 0;
56270	pos = tamanho - 7;
56271
56272	for ( var il = tamanho; il >= 1; il-- ) {
56273		soma += numeros.charAt( tamanho - il ) * pos--;
56274		if ( pos < 2 ) {
56275			pos = 9;
56276		}
56277	}
56278
56279	resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
56280
56281	if ( resultado !== parseInt( digitos.charAt( 1 ), 10 ) ) {
56282		return false;
56283	}
56284
56285	return true;
56286
56287}, "Please specify a CNPJ value number" );
56288
56289/*
56290 * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
56291 * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
56292 */
56293$.validator.addMethod( "cpfBR", function( value, element ) {
56294	"use strict";
56295
56296	if ( this.optional( element ) ) {
56297		return true;
56298	}
56299
56300	// Removing special characters from value
56301	value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
56302
56303	// Checking value to have 11 digits only
56304	if ( value.length !== 11 ) {
56305		return false;
56306	}
56307
56308	var sum = 0,
56309		firstCN, secondCN, checkResult, i;
56310
56311	firstCN = parseInt( value.substring( 9, 10 ), 10 );
56312	secondCN = parseInt( value.substring( 10, 11 ), 10 );
56313
56314	checkResult = function( sum, cn ) {
56315		var result = ( sum * 10 ) % 11;
56316		if ( ( result === 10 ) || ( result === 11 ) ) {
56317			result = 0;
56318		}
56319		return ( result === cn );
56320	};
56321
56322	// Checking for dump data
56323	if ( value === "" ||
56324		value === "00000000000" ||
56325		value === "11111111111" ||
56326		value === "22222222222" ||
56327		value === "33333333333" ||
56328		value === "44444444444" ||
56329		value === "55555555555" ||
56330		value === "66666666666" ||
56331		value === "77777777777" ||
56332		value === "88888888888" ||
56333		value === "99999999999"
56334	) {
56335		return false;
56336	}
56337
56338	// Step 1 - using first Check Number:
56339	for ( i = 1; i <= 9; i++ ) {
56340		sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 11 - i );
56341	}
56342
56343	// If first Check Number (CN) is valid, move to Step 2 - using second Check Number:
56344	if ( checkResult( sum, firstCN ) ) {
56345		sum = 0;
56346		for ( i = 1; i <= 10; i++ ) {
56347			sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 12 - i );
56348		}
56349		return checkResult( sum, secondCN );
56350	}
56351	return false;
56352
56353}, "Please specify a valid CPF number" );
56354
56355// https://jqueryvalidation.org/creditcard-method/
56356// based on https://en.wikipedia.org/wiki/Luhn_algorithm
56357$.validator.addMethod( "creditcard", function( value, element ) {
56358	if ( this.optional( element ) ) {
56359		return "dependency-mismatch";
56360	}
56361
56362	// Accept only spaces, digits and dashes
56363	if ( /[^0-9 \-]+/.test( value ) ) {
56364		return false;
56365	}
56366
56367	var nCheck = 0,
56368		nDigit = 0,
56369		bEven = false,
56370		n, cDigit;
56371
56372	value = value.replace( /\D/g, "" );
56373
56374	// Basing min and max length on
56375	// https://dev.ean.com/general-info/valid-card-types/
56376	if ( value.length < 13 || value.length > 19 ) {
56377		return false;
56378	}
56379
56380	for ( n = value.length - 1; n >= 0; n-- ) {
56381		cDigit = value.charAt( n );
56382		nDigit = parseInt( cDigit, 10 );
56383		if ( bEven ) {
56384			if ( ( nDigit *= 2 ) > 9 ) {
56385				nDigit -= 9;
56386			}
56387		}
56388
56389		nCheck += nDigit;
56390		bEven = !bEven;
56391	}
56392
56393	return ( nCheck % 10 ) === 0;
56394}, "Please enter a valid credit card number." );
56395
56396/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
56397 * Redistributed under the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
56398 * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
56399 */
56400$.validator.addMethod( "creditcardtypes", function( value, element, param ) {
56401	if ( /[^0-9\-]+/.test( value ) ) {
56402		return false;
56403	}
56404
56405	value = value.replace( /\D/g, "" );
56406
56407	var validTypes = 0x0000;
56408
56409	if ( param.mastercard ) {
56410		validTypes |= 0x0001;
56411	}
56412	if ( param.visa ) {
56413		validTypes |= 0x0002;
56414	}
56415	if ( param.amex ) {
56416		validTypes |= 0x0004;
56417	}
56418	if ( param.dinersclub ) {
56419		validTypes |= 0x0008;
56420	}
56421	if ( param.enroute ) {
56422		validTypes |= 0x0010;
56423	}
56424	if ( param.discover ) {
56425		validTypes |= 0x0020;
56426	}
56427	if ( param.jcb ) {
56428		validTypes |= 0x0040;
56429	}
56430	if ( param.unknown ) {
56431		validTypes |= 0x0080;
56432	}
56433	if ( param.all ) {
56434		validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
56435	}
56436	if ( validTypes & 0x0001 && ( /^(5[12345])/.test( value ) || /^(2[234567])/.test( value ) ) ) { // Mastercard
56437		return value.length === 16;
56438	}
56439	if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa
56440		return value.length === 16;
56441	}
56442	if ( validTypes & 0x0004 && /^(3[47])/.test( value ) ) { // Amex
56443		return value.length === 15;
56444	}
56445	if ( validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test( value ) ) { // Dinersclub
56446		return value.length === 14;
56447	}
56448	if ( validTypes & 0x0010 && /^(2(014|149))/.test( value ) ) { // Enroute
56449		return value.length === 15;
56450	}
56451	if ( validTypes & 0x0020 && /^(6011)/.test( value ) ) { // Discover
56452		return value.length === 16;
56453	}
56454	if ( validTypes & 0x0040 && /^(3)/.test( value ) ) { // Jcb
56455		return value.length === 16;
56456	}
56457	if ( validTypes & 0x0040 && /^(2131|1800)/.test( value ) ) { // Jcb
56458		return value.length === 15;
56459	}
56460	if ( validTypes & 0x0080 ) { // Unknown
56461		return true;
56462	}
56463	return false;
56464}, "Please enter a valid credit card number." );
56465
56466/**
56467 * Validates currencies with any given symbols by @jameslouiz
56468 * Symbols can be optional or required. Symbols required by default
56469 *
56470 * Usage examples:
56471 *  currency: ["£", false] - Use false for soft currency validation
56472 *  currency: ["$", false]
56473 *  currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
56474 *
56475 *  <input class="currencyInput" name="currencyInput">
56476 *
56477 * Soft symbol checking
56478 *  currencyInput: {
56479 *     currency: ["$", false]
56480 *  }
56481 *
56482 * Strict symbol checking (default)
56483 *  currencyInput: {
56484 *     currency: "$"
56485 *     //OR
56486 *     currency: ["$", true]
56487 *  }
56488 *
56489 * Multiple Symbols
56490 *  currencyInput: {
56491 *     currency: "$,£,¢"
56492 *  }
56493 */
56494$.validator.addMethod( "currency", function( value, element, param ) {
56495    var isParamString = typeof param === "string",
56496        symbol = isParamString ? param : param[ 0 ],
56497        soft = isParamString ? true : param[ 1 ],
56498        regex;
56499
56500    symbol = symbol.replace( /,/g, "" );
56501    symbol = soft ? symbol + "]" : symbol + "]?";
56502    regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$";
56503    regex = new RegExp( regex );
56504    return this.optional( element ) || regex.test( value );
56505
56506}, "Please specify a valid currency" );
56507
56508$.validator.addMethod( "dateFA", function( value, element ) {
56509	return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value );
56510}, $.validator.messages.date );
56511
56512/**
56513 * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
56514 *
56515 * @example $.validator.methods.date("01/01/1900")
56516 * @result true
56517 *
56518 * @example $.validator.methods.date("01/13/1990")
56519 * @result false
56520 *
56521 * @example $.validator.methods.date("01.01.1900")
56522 * @result false
56523 *
56524 * @example <input name="pippo" class="{dateITA:true}" />
56525 * @desc Declares an optional input element whose value must be a valid date.
56526 *
56527 * @name $.validator.methods.dateITA
56528 * @type Boolean
56529 * @cat Plugins/Validate/Methods
56530 */
56531$.validator.addMethod( "dateITA", function( value, element ) {
56532	var check = false,
56533		re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
56534		adata, gg, mm, aaaa, xdata;
56535	if ( re.test( value ) ) {
56536		adata = value.split( "/" );
56537		gg = parseInt( adata[ 0 ], 10 );
56538		mm = parseInt( adata[ 1 ], 10 );
56539		aaaa = parseInt( adata[ 2 ], 10 );
56540		xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) );
56541		if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
56542			check = true;
56543		} else {
56544			check = false;
56545		}
56546	} else {
56547		check = false;
56548	}
56549	return this.optional( element ) || check;
56550}, $.validator.messages.date );
56551
56552$.validator.addMethod( "dateNL", function( value, element ) {
56553	return this.optional( element ) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test( value );
56554}, $.validator.messages.date );
56555
56556// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
56557$.validator.addMethod( "extension", function( value, element, param ) {
56558	param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif";
56559	return this.optional( element ) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) );
56560}, $.validator.format( "Please enter a value with a valid extension." ) );
56561
56562/**
56563 * Dutch giro account numbers (not bank numbers) have max 7 digits
56564 */
56565$.validator.addMethod( "giroaccountNL", function( value, element ) {
56566	return this.optional( element ) || /^[0-9]{1,7}$/.test( value );
56567}, "Please specify a valid giro account number" );
56568
56569$.validator.addMethod( "greaterThan", function( value, element, param ) {
56570    var target = $( param );
56571
56572    if ( this.settings.onfocusout && target.not( ".validate-greaterThan-blur" ).length ) {
56573        target.addClass( "validate-greaterThan-blur" ).on( "blur.validate-greaterThan", function() {
56574            $( element ).valid();
56575        } );
56576    }
56577
56578    return value > target.val();
56579}, "Please enter a greater value." );
56580
56581$.validator.addMethod( "greaterThanEqual", function( value, element, param ) {
56582    var target = $( param );
56583
56584    if ( this.settings.onfocusout && target.not( ".validate-greaterThanEqual-blur" ).length ) {
56585        target.addClass( "validate-greaterThanEqual-blur" ).on( "blur.validate-greaterThanEqual", function() {
56586            $( element ).valid();
56587        } );
56588    }
56589
56590    return value >= target.val();
56591}, "Please enter a greater value." );
56592
56593/**
56594 * IBAN is the international bank account number.
56595 * It has a country - specific format, that is checked here too
56596 *
56597 * Validation is case-insensitive. Please make sure to normalize input yourself.
56598 */
56599$.validator.addMethod( "iban", function( value, element ) {
56600
56601	// Some quick simple tests to prevent needless work
56602	if ( this.optional( element ) ) {
56603		return true;
56604	}
56605
56606	// Remove spaces and to upper case
56607	var iban = value.replace( / /g, "" ).toUpperCase(),
56608		ibancheckdigits = "",
56609		leadingZeroes = true,
56610		cRest = "",
56611		cOperator = "",
56612		countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
56613
56614	// Check for IBAN code length.
56615	// It contains:
56616	// country code ISO 3166-1 - two letters,
56617	// two check digits,
56618	// Basic Bank Account Number (BBAN) - up to 30 chars
56619	var minimalIBANlength = 5;
56620	if ( iban.length < minimalIBANlength ) {
56621		return false;
56622	}
56623
56624	// Check the country code and find the country specific format
56625	countrycode = iban.substring( 0, 2 );
56626	bbancountrypatterns = {
56627		"AL": "\\d{8}[\\dA-Z]{16}",
56628		"AD": "\\d{8}[\\dA-Z]{12}",
56629		"AT": "\\d{16}",
56630		"AZ": "[\\dA-Z]{4}\\d{20}",
56631		"BE": "\\d{12}",
56632		"BH": "[A-Z]{4}[\\dA-Z]{14}",
56633		"BA": "\\d{16}",
56634		"BR": "\\d{23}[A-Z][\\dA-Z]",
56635		"BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
56636		"CR": "\\d{17}",
56637		"HR": "\\d{17}",
56638		"CY": "\\d{8}[\\dA-Z]{16}",
56639		"CZ": "\\d{20}",
56640		"DK": "\\d{14}",
56641		"DO": "[A-Z]{4}\\d{20}",
56642		"EE": "\\d{16}",
56643		"FO": "\\d{14}",
56644		"FI": "\\d{14}",
56645		"FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
56646		"GE": "[\\dA-Z]{2}\\d{16}",
56647		"DE": "\\d{18}",
56648		"GI": "[A-Z]{4}[\\dA-Z]{15}",
56649		"GR": "\\d{7}[\\dA-Z]{16}",
56650		"GL": "\\d{14}",
56651		"GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
56652		"HU": "\\d{24}",
56653		"IS": "\\d{22}",
56654		"IE": "[\\dA-Z]{4}\\d{14}",
56655		"IL": "\\d{19}",
56656		"IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
56657		"KZ": "\\d{3}[\\dA-Z]{13}",
56658		"KW": "[A-Z]{4}[\\dA-Z]{22}",
56659		"LV": "[A-Z]{4}[\\dA-Z]{13}",
56660		"LB": "\\d{4}[\\dA-Z]{20}",
56661		"LI": "\\d{5}[\\dA-Z]{12}",
56662		"LT": "\\d{16}",
56663		"LU": "\\d{3}[\\dA-Z]{13}",
56664		"MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
56665		"MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
56666		"MR": "\\d{23}",
56667		"MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
56668		"MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
56669		"MD": "[\\dA-Z]{2}\\d{18}",
56670		"ME": "\\d{18}",
56671		"NL": "[A-Z]{4}\\d{10}",
56672		"NO": "\\d{11}",
56673		"PK": "[\\dA-Z]{4}\\d{16}",
56674		"PS": "[\\dA-Z]{4}\\d{21}",
56675		"PL": "\\d{24}",
56676		"PT": "\\d{21}",
56677		"RO": "[A-Z]{4}[\\dA-Z]{16}",
56678		"SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
56679		"SA": "\\d{2}[\\dA-Z]{18}",
56680		"RS": "\\d{18}",
56681		"SK": "\\d{20}",
56682		"SI": "\\d{15}",
56683		"ES": "\\d{20}",
56684		"SE": "\\d{20}",
56685		"CH": "\\d{5}[\\dA-Z]{12}",
56686		"TN": "\\d{20}",
56687		"TR": "\\d{5}[\\dA-Z]{17}",
56688		"AE": "\\d{3}\\d{16}",
56689		"GB": "[A-Z]{4}\\d{14}",
56690		"VG": "[\\dA-Z]{4}\\d{16}"
56691	};
56692
56693	bbanpattern = bbancountrypatterns[ countrycode ];
56694
56695	// As new countries will start using IBAN in the
56696	// future, we only check if the countrycode is known.
56697	// This prevents false negatives, while almost all
56698	// false positives introduced by this, will be caught
56699	// by the checksum validation below anyway.
56700	// Strict checking should return FALSE for unknown
56701	// countries.
56702	if ( typeof bbanpattern !== "undefined" ) {
56703		ibanregexp = new RegExp( "^[A-Z]{2}\\d{2}" + bbanpattern + "$", "" );
56704		if ( !( ibanregexp.test( iban ) ) ) {
56705			return false; // Invalid country specific format
56706		}
56707	}
56708
56709	// Now check the checksum, first convert to digits
56710	ibancheck = iban.substring( 4, iban.length ) + iban.substring( 0, 4 );
56711	for ( i = 0; i < ibancheck.length; i++ ) {
56712		charAt = ibancheck.charAt( i );
56713		if ( charAt !== "0" ) {
56714			leadingZeroes = false;
56715		}
56716		if ( !leadingZeroes ) {
56717			ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf( charAt );
56718		}
56719	}
56720
56721	// Calculate the result of: ibancheckdigits % 97
56722	for ( p = 0; p < ibancheckdigits.length; p++ ) {
56723		cChar = ibancheckdigits.charAt( p );
56724		cOperator = "" + cRest + "" + cChar;
56725		cRest = cOperator % 97;
56726	}
56727	return cRest === 1;
56728}, "Please specify a valid IBAN" );
56729
56730$.validator.addMethod( "integer", function( value, element ) {
56731	return this.optional( element ) || /^-?\d+$/.test( value );
56732}, "A positive or negative non-decimal number please" );
56733
56734$.validator.addMethod( "ipv4", function( value, element ) {
56735	return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value );
56736}, "Please enter a valid IP v4 address." );
56737
56738$.validator.addMethod( "ipv6", function( value, element ) {
56739	return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value );
56740}, "Please enter a valid IP v6 address." );
56741
56742$.validator.addMethod( "lessThan", function( value, element, param ) {
56743    var target = $( param );
56744
56745    if ( this.settings.onfocusout && target.not( ".validate-lessThan-blur" ).length ) {
56746        target.addClass( "validate-lessThan-blur" ).on( "blur.validate-lessThan", function() {
56747            $( element ).valid();
56748        } );
56749    }
56750
56751    return value < target.val();
56752}, "Please enter a lesser value." );
56753
56754$.validator.addMethod( "lessThanEqual", function( value, element, param ) {
56755    var target = $( param );
56756
56757    if ( this.settings.onfocusout && target.not( ".validate-lessThanEqual-blur" ).length ) {
56758        target.addClass( "validate-lessThanEqual-blur" ).on( "blur.validate-lessThanEqual", function() {
56759            $( element ).valid();
56760        } );
56761    }
56762
56763    return value <= target.val();
56764}, "Please enter a lesser value." );
56765
56766$.validator.addMethod( "lettersonly", function( value, element ) {
56767	return this.optional( element ) || /^[a-z]+$/i.test( value );
56768}, "Letters only please" );
56769
56770$.validator.addMethod( "letterswithbasicpunc", function( value, element ) {
56771	return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value );
56772}, "Letters or punctuation only please" );
56773
56774// Limit the number of files in a FileList.
56775$.validator.addMethod( "maxfiles", function( value, element, param ) {
56776	if ( this.optional( element ) ) {
56777		return true;
56778	}
56779
56780	if ( $( element ).attr( "type" ) === "file" ) {
56781		if ( element.files && element.files.length > param ) {
56782			return false;
56783		}
56784	}
56785
56786	return true;
56787}, $.validator.format( "Please select no more than {0} files." ) );
56788
56789// Limit the size of each individual file in a FileList.
56790$.validator.addMethod( "maxsize", function( value, element, param ) {
56791	if ( this.optional( element ) ) {
56792		return true;
56793	}
56794
56795	if ( $( element ).attr( "type" ) === "file" ) {
56796		if ( element.files && element.files.length ) {
56797			for ( var i = 0; i < element.files.length; i++ ) {
56798				if ( element.files[ i ].size > param ) {
56799					return false;
56800				}
56801			}
56802		}
56803	}
56804
56805	return true;
56806}, $.validator.format( "File size must not exceed {0} bytes each." ) );
56807
56808// Limit the size of all files in a FileList.
56809$.validator.addMethod( "maxsizetotal", function( value, element, param ) {
56810	if ( this.optional( element ) ) {
56811		return true;
56812	}
56813
56814	if ( $( element ).attr( "type" ) === "file" ) {
56815		if ( element.files && element.files.length ) {
56816			var totalSize = 0;
56817
56818			for ( var i = 0; i < element.files.length; i++ ) {
56819				totalSize += element.files[ i ].size;
56820				if ( totalSize > param ) {
56821					return false;
56822				}
56823			}
56824		}
56825	}
56826
56827	return true;
56828}, $.validator.format( "Total size of all files must not exceed {0} bytes." ) );
56829
56830
56831$.validator.addMethod( "mobileNL", function( value, element ) {
56832	return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
56833}, "Please specify a valid mobile number" );
56834
56835$.validator.addMethod( "mobileRU", function( phone_number, element ) {
56836	var ruPhone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
56837	return this.optional( element ) || ruPhone_number.length > 9 && /^((\+7|7|8)+([0-9]){10})$/.test( ruPhone_number );
56838}, "Please specify a valid mobile number" );
56839
56840/* For UK phone functions, do the following server side processing:
56841 * Compare original input with this RegEx pattern:
56842 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
56843 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
56844 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
56845 * A number of very detailed GB telephone number RegEx patterns can also be found at:
56846 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
56847 */
56848$.validator.addMethod( "mobileUK", function( phone_number, element ) {
56849	phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
56850	return this.optional( element ) || phone_number.length > 9 &&
56851		phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ );
56852}, "Please specify a valid mobile number" );
56853
56854$.validator.addMethod( "netmask", function( value, element ) {
56855    return this.optional( element ) || /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test( value );
56856}, "Please enter a valid netmask." );
56857
56858/*
56859 * The NIE (Número de Identificación de Extranjero) is a Spanish tax identification number assigned by the Spanish
56860 * authorities to any foreigner.
56861 *
56862 * The NIE is the equivalent of a Spaniards Número de Identificación Fiscal (NIF) which serves as a fiscal
56863 * identification number. The CIF number (Certificado de Identificación Fiscal) is equivalent to the NIF, but applies to
56864 * companies rather than individuals. The NIE consists of an 'X' or 'Y' followed by 7 or 8 digits then another letter.
56865 */
56866$.validator.addMethod( "nieES", function( value, element ) {
56867	"use strict";
56868
56869	if ( this.optional( element ) ) {
56870		return true;
56871	}
56872
56873	var nieRegEx = new RegExp( /^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi );
56874	var validChars = "TRWAGMYFPDXBNJZSQVHLCKET",
56875		letter = value.substr( value.length - 1 ).toUpperCase(),
56876		number;
56877
56878	value = value.toString().toUpperCase();
56879
56880	// Quick format test
56881	if ( value.length > 10 || value.length < 9 || !nieRegEx.test( value ) ) {
56882		return false;
56883	}
56884
56885	// X means same number
56886	// Y means number + 10000000
56887	// Z means number + 20000000
56888	value = value.replace( /^[X]/, "0" )
56889		.replace( /^[Y]/, "1" )
56890		.replace( /^[Z]/, "2" );
56891
56892	number = value.length === 9 ? value.substr( 0, 8 ) : value.substr( 0, 9 );
56893
56894	return validChars.charAt( parseInt( number, 10 ) % 23 ) === letter;
56895
56896}, "Please specify a valid NIE number." );
56897
56898/*
56899 * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
56900 */
56901$.validator.addMethod( "nifES", function( value, element ) {
56902	"use strict";
56903
56904	if ( this.optional( element ) ) {
56905		return true;
56906	}
56907
56908	value = value.toUpperCase();
56909
56910	// Basic format test
56911	if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
56912		return false;
56913	}
56914
56915	// Test NIF
56916	if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
56917		return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
56918	}
56919
56920	// Test specials NIF (starts with K, L or M)
56921	if ( /^[KLM]{1}/.test( value ) ) {
56922		return ( value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 1 ) % 23 ) );
56923	}
56924
56925	return false;
56926
56927}, "Please specify a valid NIF number." );
56928
56929/*
56930 * Numer identyfikacji podatkowej ( NIP ) is the way tax identification used in Poland for companies
56931 */
56932$.validator.addMethod( "nipPL", function( value ) {
56933	"use strict";
56934
56935	value = value.replace( /[^0-9]/g, "" );
56936
56937	if ( value.length !== 10 ) {
56938		return false;
56939	}
56940
56941	var arrSteps = [ 6, 5, 7, 2, 3, 4, 5, 6, 7 ];
56942	var intSum = 0;
56943	for ( var i = 0; i < 9; i++ ) {
56944		intSum += arrSteps[ i ] * value[ i ];
56945	}
56946	var int2 = intSum % 11;
56947	var intControlNr = ( int2 === 10 ) ? 0 : int2;
56948
56949	return ( intControlNr === parseInt( value[ 9 ], 10 ) );
56950}, "Please specify a valid NIP number." );
56951
56952/**
56953 * Created for project jquery-validation.
56954 * @Description Brazillian PIS or NIS number (Número de Identificação Social Pis ou Pasep) is the equivalent of a
56955 * Brazilian tax registration number NIS of PIS numbers have 11 digits in total: 10 numbers followed by 1 check numbers
56956 * that are being used for validation.
56957 * @copyright (c) 21/08/2018 13:14, Cleiton da Silva Mendonça
56958 * @author Cleiton da Silva Mendonça <[email protected]>
56959 * @link http://gitlab.com/csmendonca Gitlab of Cleiton da Silva Mendonça
56960 * @link http://github.com/csmendonca Github of Cleiton da Silva Mendonça
56961 */
56962$.validator.addMethod( "nisBR", function( value ) {
56963	var number;
56964	var cn;
56965	var sum = 0;
56966	var dv;
56967	var count;
56968	var multiplier;
56969
56970	// Removing special characters from value
56971	value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
56972
56973	// Checking value to have 11 digits only
56974	if ( value.length !== 11 ) {
56975		return false;
56976	}
56977
56978	//Get check number of value
56979	cn = parseInt( value.substring( 10, 11 ), 10 );
56980
56981	//Get number with 10 digits of the value
56982	number = parseInt( value.substring( 0, 10 ), 10 );
56983
56984	for ( count = 2; count < 12; count++ ) {
56985		multiplier = count;
56986		if ( count === 10 ) {
56987			multiplier = 2;
56988		}
56989		if ( count === 11 ) {
56990			multiplier = 3;
56991		}
56992		sum += ( ( number % 10 ) * multiplier );
56993		number = parseInt( number / 10, 10 );
56994	}
56995	dv = ( sum % 11 );
56996
56997	if ( dv > 1 ) {
56998		dv = ( 11 - dv );
56999	} else {
57000		dv = 0;
57001	}
57002
57003	if ( cn === dv ) {
57004		return true;
57005	} else {
57006		return false;
57007	}
57008}, "Please specify a valid NIS/PIS number" );
57009
57010$.validator.addMethod( "notEqualTo", function( value, element, param ) {
57011	return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param );
57012}, "Please enter a different value, values must not be the same." );
57013
57014$.validator.addMethod( "nowhitespace", function( value, element ) {
57015	return this.optional( element ) || /^\S+$/i.test( value );
57016}, "No white space please" );
57017
57018/**
57019* Return true if the field value matches the given format RegExp
57020*
57021* @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
57022* @result true
57023*
57024* @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
57025* @result false
57026*
57027* @name $.validator.methods.pattern
57028* @type Boolean
57029* @cat Plugins/Validate/Methods
57030*/
57031$.validator.addMethod( "pattern", function( value, element, param ) {
57032	if ( this.optional( element ) ) {
57033		return true;
57034	}
57035	if ( typeof param === "string" ) {
57036		param = new RegExp( "^(?:" + param + ")$" );
57037	}
57038	return param.test( value );
57039}, "Invalid format." );
57040
57041/**
57042 * Dutch phone numbers have 10 digits (or 11 and start with +31).
57043 */
57044$.validator.addMethod( "phoneNL", function( value, element ) {
57045	return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
57046}, "Please specify a valid phone number." );
57047
57048/**
57049 * Polish telephone numbers have 9 digits.
57050 *
57051 * Mobile phone numbers starts with following digits:
57052 * 45, 50, 51, 53, 57, 60, 66, 69, 72, 73, 78, 79, 88.
57053 *
57054 * Fixed-line numbers starts with area codes:
57055 * 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 29, 32, 33,
57056 * 34, 41, 42, 43, 44, 46, 48, 52, 54, 55, 56, 58, 59, 61,
57057 * 62, 63, 65, 67, 68, 71, 74, 75, 76, 77, 81, 82, 83, 84,
57058 * 85, 86, 87, 89, 91, 94, 95.
57059 *
57060 * Ministry of National Defence numbers and VoIP numbers starts with 26 and 39.
57061 *
57062 * Excludes intelligent networks (premium rate, shared cost, free phone numbers).
57063 *
57064 * Poland National Numbering Plan http://www.itu.int/oth/T02020000A8/en
57065 */
57066$.validator.addMethod( "phonePL", function( phone_number, element ) {
57067	phone_number = phone_number.replace( /\s+/g, "" );
57068	var regexp = /^(?:(?:(?:\+|00)?48)|(?:\(\+?48\)))?(?:1[2-8]|2[2-69]|3[2-49]|4[1-68]|5[0-9]|6[0-35-9]|[7-8][1-9]|9[145])\d{7}$/;
57069	return this.optional( element ) || regexp.test( phone_number );
57070}, "Please specify a valid phone number" );
57071
57072/* For UK phone functions, do the following server side processing:
57073 * Compare original input with this RegEx pattern:
57074 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
57075 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
57076 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
57077 * A number of very detailed GB telephone number RegEx patterns can also be found at:
57078 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
57079 */
57080
57081// Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
57082$.validator.addMethod( "phonesUK", function( phone_number, element ) {
57083	phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
57084	return this.optional( element ) || phone_number.length > 9 &&
57085		phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ );
57086}, "Please specify a valid uk phone number" );
57087
57088/* For UK phone functions, do the following server side processing:
57089 * Compare original input with this RegEx pattern:
57090 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
57091 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
57092 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
57093 * A number of very detailed GB telephone number RegEx patterns can also be found at:
57094 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
57095 */
57096$.validator.addMethod( "phoneUK", function( phone_number, element ) {
57097	phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
57098	return this.optional( element ) || phone_number.length > 9 &&
57099		phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ );
57100}, "Please specify a valid phone number" );
57101
57102/**
57103 * Matches US phone number format
57104 *
57105 * where the area code may not start with 1 and the prefix may not start with 1
57106 * allows '-' or ' ' as a separator and allows parens around area code
57107 * some people may want to put a '1' in front of their number
57108 *
57109 * 1(212)-999-2345 or
57110 * 212 999 2344 or
57111 * 212-999-0983
57112 *
57113 * but not
57114 * 111-123-5434
57115 * and not
57116 * 212 123 4567
57117 */
57118$.validator.addMethod( "phoneUS", function( phone_number, element ) {
57119	phone_number = phone_number.replace( /\s+/g, "" );
57120	return this.optional( element ) || phone_number.length > 9 &&
57121		phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]\d{2}-?\d{4}$/ );
57122}, "Please specify a valid phone number" );
57123
57124/*
57125* Valida CEPs do brasileiros:
57126*
57127* Formatos aceitos:
57128* 99999-999
57129* 99.999-999
57130* 99999999
57131*/
57132$.validator.addMethod( "postalcodeBR", function( cep_value, element ) {
57133	return this.optional( element ) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
57134}, "Informe um CEP válido." );
57135
57136/**
57137 * Matches a valid Canadian Postal Code
57138 *
57139 * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
57140 * @result true
57141 *
57142 * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
57143 * @result false
57144 *
57145 * @name jQuery.validator.methods.postalCodeCA
57146 * @type Boolean
57147 * @cat Plugins/Validate/Methods
57148 */
57149$.validator.addMethod( "postalCodeCA", function( value, element ) {
57150	return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value );
57151}, "Please specify a valid postal code" );
57152
57153/* Matches Italian postcode (CAP) */
57154$.validator.addMethod( "postalcodeIT", function( value, element ) {
57155	return this.optional( element ) || /^\d{5}$/.test( value );
57156}, "Please specify a valid postal code" );
57157
57158$.validator.addMethod( "postalcodeNL", function( value, element ) {
57159	return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value );
57160}, "Please specify a valid postal code" );
57161
57162// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
57163$.validator.addMethod( "postcodeUK", function( value, element ) {
57164	return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value );
57165}, "Please specify a valid UK postcode
vendor: 5,517 bytes, lines 57165-57302
57165" );
57166
57167/*
57168 * Lets you say "at least X inputs that match selector Y must be filled."
57169 *
57170 * The end result is that neither of these inputs:
57171 *
57172 *	<input class="productinfo" name="partnumber">
57173 *	<input class="productinfo" name="description">
57174 *
57175 *	...will validate unless at least one of them is filled.
57176 *
57177 * partnumber:	{require_from_group: [1,".productinfo"]},
57178 * description: {require_from_group: [1,".productinfo"]}
57179 *
57180 * options[0]: number of fields that must be filled in the group
57181 * options[1]: CSS selector that defines the group of conditionally required fields
57182 */
57183$.validator.addMethod( "require_from_group", function( value, element, options ) {
57184	var $fields = $( options[ 1 ], element.form ),
57185		$fieldsFirst = $fields.eq( 0 ),
57186		validator = $fieldsFirst.data( "valid_req_grp" ) ? $fieldsFirst.data( "valid_req_grp" ) : $.extend( {}, this ),
57187		isValid = $fields.filter( function() {
57188			return validator.elementValue( this );
57189		} ).length >= options[ 0 ];
57190
57191	// Store the cloned validator for future validation
57192	$fieldsFirst.data( "valid_req_grp", validator );
57193
57194	// If element isn't being validated, run each require_from_group field's validation rules
57195	if ( !$( element ).data( "being_validated" ) ) {
57196		$fields.data( "being_validated", true );
57197		$fields.each( function() {
57198			validator.element( this );
57199		} );
57200		$fields.data( "being_validated", false );
57201	}
57202	return isValid;
57203}, $.validator.format( "Please fill at least {0} of these fields." ) );
57204
57205/*
57206 * Lets you say "either at least X inputs that match selector Y must be filled,
57207 * OR they must all be skipped (left blank)."
57208 *
57209 * The end result, is that none of these inputs:
57210 *
57211 *	<input class="productinfo" name="partnumber">
57212 *	<input class="productinfo" name="description">
57213 *	<input class="productinfo" name="color">
57214 *
57215 *	...will validate unless either at least two of them are filled,
57216 *	OR none of them are.
57217 *
57218 * partnumber:	{skip_or_fill_minimum: [2,".productinfo"]},
57219 * description: {skip_or_fill_minimum: [2,".productinfo"]},
57220 * color:		{skip_or_fill_minimum: [2,".productinfo"]}
57221 *
57222 * options[0]: number of fields that must be filled in the group
57223 * options[1]: CSS selector that defines the group of conditionally required fields
57224 *
57225 */
57226$.validator.addMethod( "skip_or_fill_minimum", function( value, element, options ) {
57227	var $fields = $( options[ 1 ], element.form ),
57228		$fieldsFirst = $fields.eq( 0 ),
57229		validator = $fieldsFirst.data( "valid_skip" ) ? $fieldsFirst.data( "valid_skip" ) : $.extend( {}, this ),
57230		numberFilled = $fields.filter( function() {
57231			return validator.elementValue( this );
57232		} ).length,
57233		isValid = numberFilled === 0 || numberFilled >= options[ 0 ];
57234
57235	// Store the cloned validator for future validation
57236	$fieldsFirst.data( "valid_skip", validator );
57237
57238	// If element isn't being validated, run each skip_or_fill_minimum field's validation rules
57239	if ( !$( element ).data( "being_validated" ) ) {
57240		$fields.data( "being_validated", true );
57241		$fields.each( function() {
57242			validator.element( this );
57243		} );
57244		$fields.data( "being_validated", false );
57245	}
57246	return isValid;
57247}, $.validator.format( "Please either skip these fields or fill at least {0} of them." ) );
57248
57249/* Validates US States and/or Territories by @jdforsythe
57250 * Can be case insensitive or require capitalization - default is case insensitive
57251 * Can include US Territories or not - default does not
57252 * Can include US Military postal abbreviations (AA, AE, AP) - default does not
57253 *
57254 * Note: "States" always includes DC (District of Colombia)
57255 *
57256 * Usage examples:
57257 *
57258 *  This is the default - case insensitive, no territories, no military zones
57259 *  stateInput: {
57260 *     caseSensitive: false,
57261 *     includeTerritories: false,
57262 *     includeMilitary: false
57263 *  }
57264 *
57265 *  Only allow capital letters, no territories, no military zones
57266 *  stateInput: {
57267 *     caseSensitive: false
57268 *  }
57269 *
57270 *  Case insensitive, include territories but not military zones
57271 *  stateInput: {
57272 *     includeTerritories: true
57273 *  }
57274 *
57275 *  Only allow capital letters, include territories and military zones
57276 *  stateInput: {
57277 *     caseSensitive: true,
57278 *     includeTerritories: true,
57279 *     includeMilitary: true
57280 *  }
57281 *
57282 */
57283$.validator.addMethod( "stateUS", function( value, element, options ) {
57284	var isDefault = typeof options === "undefined",
57285		caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
57286		includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
57287		includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
57288		regex;
57289
57290	if ( !includeTerritories && !includeMilitary ) {
57291		regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
57292	} else if ( includeTerritories && includeMilitary ) {
57293		regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
57294	} else if ( includeTerritories ) {
57295		regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
57296	} else {
57297		regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
57298	}
57299
57300	regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" );
57301	return this.optional( element ) || regex.test( value );
57302}, "Please specify a valid state
vendor: 2,891 bytes, lines 57302-57343
57302" );
57303
57304// TODO check if value starts with <, otherwise don't try stripping anything
57305$.validator.addMethod( "strippedminlength", function( value, element, param ) {
57306	return $( value ).text().length >= param;
57307}, $.validator.format( "Please enter at least {0} characters" ) );
57308
57309$.validator.addMethod( "time", function( value, element ) {
57310	return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value );
57311}, "Please enter a valid time, between 00:00 and 23:59" );
57312
57313$.validator.addMethod( "time12h", function( value, element ) {
57314	return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
57315}, "Please enter a valid time in 12-hour am/pm format" );
57316
57317// Same as url, but TLD is optional
57318$.validator.addMethod( "url2", function( value, element ) {
57319	return this.optional( element ) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value );
57320}, $.validator.messages.url );
57321
57322/**
57323 * Return true, if the value is a valid vehicle identification number (VIN).
57324 *
57325 * Works with all kind of text inputs.
57326 *
57327 * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
57328 * @desc Declares a required input element whose value must be a valid vehicle identification number.
57329 *
57330 * @name $.validator.methods.vinUS
57331 * @type Boolean
57332 * @cat Plugins/Validate/Methods
57333 */
57334$.validator.addMethod( "vinUS", function( v ) {
57335	if ( v.length !== 17 ) {
57336		return false;
57337	}
57338
57339	var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ],
57340		VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
57341		FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
57342		rs = 0,
57343		i, n, d, f, cd, cdv;
57344
57345	for ( i = 0; i < 17; i++ ) {
57346		f = FL[ i ];
57347		d = v.slice( i, i + 1 );
57348		if ( i === 8 ) {
57349			cdv = d;
57350		}
57351		if ( !isNaN( d ) ) {
57352			d *= f;
57353		} else {
57354			for ( n = 0; n < LL.length; n++ ) {
57355				if ( d.toUpperCase() === LL[ n ] ) {
57356					d = VL[ n ];
57357					d *= f;
57358					if ( isNaN( cdv ) && n === 8 ) {
57359						cdv = LL[ n ];
57360					}
57361					break;
57362				}
57363			}
57364		}
57365		rs += d;
57366	}
57367	cd = rs % 11;
57368	if ( cd === 10 ) {
57369		cd = "X";
57370	}
57371	if ( cd === cdv ) {
57372		return true;
57373	}
57374	return false;
57375}, "The specified vehicle identification number (VIN) is invalid." );
57376
57377$.validator.addMethod( "zipcodeUS", function( value, element ) {
57378	return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value );
57379}, "The specified US ZIP Code is invalid" );
57380
57381$.validator.addMethod( "ziprange", function( value, element ) {
57382	return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value );
57383}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx" );
57384return $;
57385}));
57386"use strict";
57387var valGetParentContainer = function(element) {
57388    var element = $(element);
57389
57390    if ($(element).closest('.form-group-sub').length > 0) {
57391        return $(element).closest('.form-group-sub')
57392    } else if ($(element).closest('.bootstrap-select').length > 0) {
57393        return $(element).closest('.bootstrap-select')
57394    } else {
57395        return $(element).closest('.form-group');
57396    }
57397}
57398
57399jQuery.validator.setDefaults({
57400    errorElement: 'div', //default input error message container
57401    focusInvalid: false, // do not focus the last invalid input
57402    ignore: "",  // validate all fields including form hidden input
57403
57404    errorPlacement: function(error, element) { // render error placement for each input type
57405        var element = $(element);
57406
57407        var group = valGetParentContainer(element);
57408        var help = group.find('.form-text');
57409
57410        if (group.find('.valid-feedback, .invalid-feedback').length !== 0) {
57411            return;
57412        }
57413
57414        element.addClass('is-invalid');
57415        error.addClass('invalid-feedback');
57416
57417        if (help.length > 0) {
57418            help.before(error);
57419        } else {
57420            if (element.closest('.bootstrap-select').length > 0) {     //Bootstrap select
57421                element.closest('.bootstrap-select').find('.bs-placeholder').after(error);
57422            } else if (element.closest('.input-group').length > 0) {   //Bootstrap group
57423                element.after(error);
57424            } else {                                                   //Checkbox & radios
57425                if (element.is(':checkbox')) {
57426                    element.closest('.kt-checkbox').find('> span').after(error);
57427                } else {
57428                    element.after(error);
57429                }                
57430            }            
57431        }
57432    },
57433
57434    highlight: function(element) { // hightlight error inputs
57435        var group = valGetParentContainer(element);
57436        group.addClass('validate');
57437        group.addClass('is-invalid');
57438        $(element).removeClass('is-valid');
57439    },
57440
57441    unhighlight: function(element) { // revert the change done by hightlight
57442        var group = valGetParentContainer(element);
57443        group.removeClass('validate'); 
57444        group.removeClass('is-invalid'); 
57445        $(element).removeClass('is-invalid');
57446    },
57447
57448    success: function(label, element) {
57449        var group = valGetParentContainer(element);
57450        group.removeClass('validate');
57451        group.find('.invalid-feedback').remove();
57452    }
57453});
57454
57455jQuery.validator.addMethod("email", function(value, element) {
57456    if (/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(value)) {
57457        return true;
57458    } else {
57459        return false;
57460    }
57461}, "Please enter a valid Email.");
57462!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;
vendor: 7,322 bytes, lines 57462-57505
57462o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'<button type="button">&times;</button>',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&#39;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e("<div/>"),M=e("<div/>"),B=e("<div/>"),q=e("<div/>"),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.4",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
57463//# sourceMappingURL=toastr.js.map
57464
57465// ┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐ \\
57466// │ Raphaël 2.2.8 - JavaScript Vector Library                                                             │ \\
57467// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
57468// │ Copyright © 2008-2016 Dmitry Baranovskiy (http://raphaeljs.com)                                       │ \\
57469// │ Copyright © 2008-2016 Sencha Labs (http://sencha.com)                                                 │ \\
57470// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
57471// │ Licensed under the MIT (https://github.com/DmitryBaranovskiy/raphael/blob/master/license.txt) license.│ \\
57472// └───────────────────────────────────────────────────────────────────────────────────────────────────────┘ \\
57473
57474(function webpackUniversalModuleDefinition(root, factory) {
57475	if(typeof exports === 'object' && typeof module === 'object')
57476		module.exports = factory();
57477	else if(typeof define === 'function' && define.amd)
57478		define([], factory);
57479	else if(typeof exports === 'object')
57480		exports["Raphael"] = factory();
57481	else
57482		root["Raphael"] = factory();
57483})(window, function() {
57484return /******/ (function(modules) { // webpackBootstrap
57485/******/ 	// The module cache
57486/******/ 	var installedModules = {};
57487/******/
57488/******/ 	// The require function
57489/******/ 	function __webpack_require__(moduleId) {
57490/******/
57491/******/ 		// Check if module is in cache
57492/******/ 		if(installedModules[moduleId]) {
57493/******/ 			return installedModules[moduleId].exports;
57494/******/ 		}
57495/******/ 		// Create a new module (and put it into the cache)
57496/******/ 		var module = installedModules[moduleId] = {
57497/******/ 			i: moduleId,
57498/******/ 			l: false,
57499/******/ 			exports: {}
57500/******/ 		};
57501/******/
57502/******/ 		// Execute the module function
57503/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
57504/******/
57505/******/ 		// Flag the module as loaded
vendor: 2,843 bytes, lines 57506-57571
57506/******/ 		module.l = true;
57507/******/
57508/******/ 		// Return the exports of the module
57509/******/ 		return module.exports;
57510/******/ 	}
57511/******/
57512/******/
57513/******/ 	// expose the modules object (__webpack_modules__)
57514/******/ 	__webpack_require__.m = modules;
57515/******/
57516/******/ 	// expose the module cache
57517/******/ 	__webpack_require__.c = installedModules;
57518/******/
57519/******/ 	// define getter function for harmony exports
57520/******/ 	__webpack_require__.d = function(exports, name, getter) {
57521/******/ 		if(!__webpack_require__.o(exports, name)) {
57522/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
57523/******/ 		}
57524/******/ 	};
57525/******/
57526/******/ 	// define __esModule on exports
57527/******/ 	__webpack_require__.r = function(exports) {
57528/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
57529/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
57530/******/ 		}
57531/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
57532/******/ 	};
57533/******/
57534/******/ 	// create a fake namespace object
57535/******/ 	// mode & 1: value is a module id, require it
57536/******/ 	// mode & 2: merge all properties of value into the ns
57537/******/ 	// mode & 4: return value when already ns object
57538/******/ 	// mode & 8|1: behave like require
57539/******/ 	__webpack_require__.t = function(value, mode) {
57540/******/ 		if(mode & 1) value = __webpack_require__(value);
57541/******/ 		if(mode & 8) return value;
57542/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
57543/******/ 		var ns = Object.create(null);
57544/******/ 		__webpack_require__.r(ns);
57545/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
57546/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
57547/******/ 		return ns;
57548/******/ 	};
57549/******/
57550/******/ 	// getDefaultExport function for compatibility with non-harmony modules
57551/******/ 	__webpack_require__.n = function(module) {
57552/******/ 		var getter = module && module.__esModule ?
57553/******/ 			function getDefault() { return module['default']; } :
57554/******/ 			function getModuleExports() { return module; };
57555/******/ 		__webpack_require__.d(getter, 'a', getter);
57556/******/ 		return getter;
57557/******/ 	};
57558/******/
57559/******/ 	// Object.prototype.hasOwnProperty.call
57560/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
57561/******/
57562/******/ 	// __webpack_public_path__
57563/******/ 	__webpack_require__.p = "";
57564/******/
57565/******/
57566/******/ 	// Load entry module and return exports
57567/******/ 	return __webpack_require__(__webpack_require__.s = "./dev/raphael.amd.js");
57568/******/ })
57569/************************************************************************/
57570/******/ ({
57571
57572/***/ "./dev/raphael.amd.js":
57573/*!****************************!*\
57574  !*** ./dev/raphael.amd.js ***!
57575  \****************************/
57576/*! no static exports found */
57577/***/ (function(module, exports, __webpack_require__) {
57578
57579eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ \"./dev/raphael.core.js\"), __webpack_require__(/*! ./raphael.svg */ \"./dev/raphael.svg.js\"), __webpack_require__(/*! ./raphael.vml */ \"./dev/raphael.vml.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {\n\n    return R;\n\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC5hbWQuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SYXBoYWVsLy4vZGV2L3JhcGhhZWwuYW1kLmpzPzM1NjQiXSwic291cmNlc0NvbnRlbnQiOlsiZGVmaW5lKFtcIi4vcmFwaGFlbC5jb3JlXCIsIFwiLi9yYXBoYWVsLnN2Z1wiLCBcIi4vcmFwaGFlbC52bWxcIl0sIGZ1bmN0aW9uKFIpIHtcblxuICAgIHJldHVybiBSO1xuXG59KTsiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./dev/raphael.amd.js\n");
57580
57581/***/ }),
57582
57583/***/ "./dev/raphael.core.js":
57584/*!*****************************!*\
57585  !*** ./dev/raphael.core.js ***!
57586  \*****************************/
57587/*! no static exports found */
57588/***/ (function(module, exports, __webpack_require__) {
57589
57590eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! eve */ \"./node_modules/eve-raphael/eve.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(eve) {\n\n    /*\\\n     * Raphael\n     [ method ]\n     **\n     * Creates a canvas object on which to draw.\n     * You must do this first, as all future calls to drawing methods\n     * from this instance will be bound to this canvas.\n     > Parameters\n     **\n     - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface\n     - width (number)\n     - height (number)\n     - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n     * or\n     - x (number)\n     - y (number)\n     - width (number)\n     - height (number)\n     - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n     * or\n     - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add.\n     - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n     * or\n     - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`.\n     = (object) @Paper\n     > Usage\n     | // Each of the following examples create a canvas\n     | // that is 320px wide by 200px high.\n     | // Canvas is created at the viewport’s 10,50 coordinate.\n     | var paper = Raphael(10, 50, 320, 200);\n     | // Canvas is created at the top left corner of the #notepad element\n     | // (or its top right corner in dir=\"rtl\" elements)\n     | var paper = Raphael(document.getElementById(\"notepad\"), 320, 200);\n     | // Same as above\n     | var paper = Raphael(\"notepad\", 320, 200);\n     | // Image dump\n     | var set = Raphael([\"notepad\", 320, 200, {\n     |     type: \"rect\",\n     |     x: 10,\n     |     y: 10,\n     |     width: 25,\n     |     height: 25,\n     |     stroke: \"#f00\"\n     | }, {\n     |     type: \"text\",\n     |     x: 30,\n     |     y: 40,\n     |     text: \"Dump\"\n     | }]);\n    \\*/\n    function R(first) {\n        if (R.is(first, \"function\")) {\n            return loaded ? first() : eve.on(\"raphael.DOMload\", first);\n        } else if (R.is(first, array)) {\n            return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);\n        } else {\n            var args = Array.prototype.slice.call(arguments, 0);\n            if (R.is(args[args.length - 1], \"function\")) {\n                var f = args.pop();\n                return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on(\"raphael.DOMload\", function () {\n                    f.call(R._engine.create[apply](R, args));\n                });\n            } else {\n                return R._engine.create[apply](R, arguments);\n            }\n        }\n    }\n    R.version = \"2.2.0\";\n    R.eve = eve;\n    var loaded,\n        separator = /[, ]+/,\n        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},\n        formatrg = /\\{(\\d+)\\}/g,\n        proto = \"prototype\",\n        has = \"hasOwnProperty\",\n        g = {\n            doc: document,\n            win: window\n        },\n        oldRaphael = {\n            was: Object.prototype[has].call(g.win, \"Raphael\"),\n            is: g.win.Raphael\n        },\n        Paper = function () {\n            /*\\\n             * Paper.ca\n             [ property (object) ]\n             **\n             * Shortcut for @Paper.customAttributes\n            \\*/\n            /*\\\n             * Paper.customAttributes\n             [ property (object) ]\n             **\n             * If you have a set of attributes that you would like to represent\n             * as a function of some number you can do it easily with custom attributes:\n             > Usage\n             | paper.customAttributes.hue = function (num) {\n             |     num = num % 1;\n             |     return {fill: \"hsb(\" + num + \", 0.75, 1)\"};\n             | };\n             | // Custom attribute “hue” will change fill\n             | // to be given hue with fixed saturation and brightness.\n             | // Now you can use it like this:\n             | var c = paper.circle(10, 10, 10).attr({hue: .45});\n             | // or even like this:\n             | c.animate({hue: 1}, 1e3);\n             |\n             | // You could also create custom attribute\n             | // with multiple parameters:\n             | paper.customAttributes.hsb = function (h, s, b) {\n             |     return {fill: \"hsb(\" + [h, s, b].join(\",\") + \")\"};\n             | };\n             | c.attr({hsb: \"0.5 .8 1\"});\n             | c.animate({hsb: [1, 0, 0.5]}, 1e3);\n            \\*/\n            this.ca = this.customAttributes = {};\n        },\n        paperproto,\n        appendChild = \"appendChild\",\n        apply = \"apply\",\n        concat = \"concat\",\n        //taken from Modernizr touch test: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js#L40\n        supportsTouch = ('ontouchstart' in window) || window.TouchEvent || window.DocumentTouch && document instanceof DocumentTouch,\n        E = \"\",\n        S = \" \",\n        Str = String,\n        split = \"split\",\n        events = \"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[split](S),\n        touchMap = {\n            mousedown: \"touchstart\",\n            mousemove: \"touchmove\",\n            mouseup: \"touchend\"\n        },\n        lowerCase = Str.prototype.toLowerCase,\n        math = Math,\n        mmax = math.max,\n        mmin = math.min,\n        abs = math.abs,\n        pow = math.pow,\n        PI = math.PI,\n        nu = \"number\",\n        str
57590ing = \"string\",\n        array = \"array\",\n        toString = \"toString\",\n        fillString = \"fill\",\n        objectToString = Object.prototype.toString,\n        paper = {},\n        push = \"push\",\n        ISURL = R._ISURL = /^url\\(['\"]?(.+?)['\"]?\\)$/i,\n        colourRegExp = /^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i,\n        isnan = {\"NaN\": 1, \"Infinity\": 1, \"-Infinity\": 1},\n        bezierrg = /^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,\n        round = math.round,\n        setAttribute = \"setAttribute\",\n        toFloat = parseFloat,\n        toInt = parseInt,\n        upperCase = Str.prototype.toUpperCase,\n        availableAttrs = R._availableAttrs = {\n            \"arrow-end\": \"none\",\n            \"arrow-start\": \"none\",\n            blur: 0,\n            \"clip-rect\": \"0 0 1e9 1e9\",\n            cursor: \"default\",\n            cx: 0,\n            cy: 0,\n            fill: \"#fff\",\n            \"fill-opacity\": 1,\n            font: '10px \"Arial\"',\n            \"font-family\": '\"Arial\"',\n            \"font-size\": \"10\",\n            \"font-style\": \"normal\",\n            \"font-weight\"
57590: 400,\n            gradient: 0,\n            height: 0,\n            href: \"http://raphaeljs.com/\",\n            \"letter-spacing\": 0,\n            opacity: 1,\n            path: \"M0,0\",\n            r: 0,\n            rx: 0,\n            ry: 0,\n            src: \"\",\n            stroke: \"#000\",\n            \"stroke-dasharray\": \"\",\n            \"stroke-linecap\": \"butt\",\n            \"stroke-linejoin\": \"butt\",\n            \"stroke-miterlimit\": 0,\n            \"stroke-opacity\": 1,\n            \"stroke-width\": 1,\n            target: \"_blank\",\n            \"text-anchor\": \"middle\",\n            title: \"Raphael\",\n            transform: \"\",\n            width: 0,\n            x: 0,\n            y: 0,\n            \"class\": \"\"\n        },\n        availableAnimAttrs = R._availableAnimAttrs = {\n            blur: nu,\n            \"clip-rect\": \"csv\",\n            cx: nu,\n            cy: nu,\n            fill: \"colour\",\n            \"fill-opacity\": nu,\n            \"font-size\": nu,\n            height: nu,\n            opacity: nu,\n            path: \"path\",\n            r: nu,\n            rx: nu,\n            ry: nu,\n            stroke: \"colour\",\n            \"stroke-opacity\": nu,\n            \"stroke-width\": nu,\n            transform: \"transform\",\n            width: nu,\n            x: nu,\n            y: nu\n        },\n        whitespace = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]/g,\n        commaSpaces = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,\n        hsrg = {hs: 1, rg: 1},\n        p2s = /,?([achlmqrstvxz]),?/gi,\n        pathCommand = /([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n        tCommand = /([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n        pathValues = /(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/ig,\n        radial_gradient = R._radial_gradient = /^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,\n        eldata = {},\n        sortByKey = function (a, b) {\n            return a.key - b.key;\n        },\n        sortByNumber = function (a, b) {\n            return toFloat(a) - toFloat(b);\n        },\n        fun = function () {},\n        pipe = function (x) {\n            return x;\n        },\n        rectPath = R._rectPath = function (x, y, w, h, r) {\n            if (r) {\n                return [[\"M\", x + r, y], [\"l\", w - r * 2, 0], [\"a\", r, r, 0, 0, 1, r, r], [\"l\", 0, h - r * 2], [\"a\", r, r, 0, 0, 1, -r, r], [\"l\", r * 2 - w, 0], [\"a\", r, r, 0, 0, 1, -r, -r], [\"l\", 0, r * 2 - h], [\"a\", r, r, 0, 0, 1, r, -r], [\"z\"]];\n            }\n            return [[\"M\", x, y], [\"l\", w, 0], [\"l\", 0, h], [\"l\", -w, 0], [\"z\"]];\n        },\n        ellipsePath = function (x, y, rx, ry) {\n            if (ry == null) {\n                ry = rx;\n            }\n            return [[\"M\", x, y], [\"m\", 0, -ry], [\"a\", rx, ry, 0, 1, 1, 0, 2 * ry], [\"a\", rx, ry, 0, 1, 1, 0, -2 * ry], [\"z\"]];\n        },\n        getPath = R._getPath = {\n            path: function (el) {\n                return el.attr(\"path\");\n            },\n            circle: function (el) {\n                var a = el.attrs;\n                return ellipsePath(a.cx, a.cy, a.r);\n            },\n            ellipse: function (el) {\n                var a = el.attrs;\n                return ellipsePath(a.cx, a.cy, a.rx, a.ry);\n            },\n            rect: function (el) {\n                var a = el.attrs;\n                return rectPath(a.x, a.y, a.width, a.height, a.r);\n            },\n            image: function (el) {\n                var a = el.attrs;\n                return rectPath(a.x, a.y, a.width, a.height);\n            },\n            text: function (el) {\n                var bbox = el._getBBox();\n                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n            },\n            set : function(el) {\n                var bbox = el._getBBox();\n                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n            }\n        },\n        /*\\\n         * Raphael.mapPath\n         [ method ]\n         **\n         * Transform the path string with given matrix.\n         > Parameters\n         - path (string) path string\n         - matrix (object) see @Matrix\n         = (string) transformed path string\n        \\*/\n        mapPath = R.mapPath = function (path, matrix) {\n            if (!matrix) {\n                return path;\n            }\n            var x, y, i, j, ii, jj, pathi;\n            path = path2curve(path);\n            for (i = 0, ii = path.length; i < ii;
57590 i++) {\n                pathi = path[i];\n                for (j = 1, jj = pathi.length; j < jj; j += 2) {\n                    x = matrix.x(pathi[j], pathi[j + 1]);\n                    y = matrix.y(pathi[j], pathi[j + 1]);\n                    pathi[j] = x;\n                    pathi[j + 1] = y;\n                }\n            }\n            return path;\n        };\n\n    R._g = g;\n    /*\\\n     * Raphael.type\n     [ property (string) ]\n     **\n     * Can be “SVG”, “VML” or empty, depending on browser support.\n    \\*/\n    R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\", \"1.1\") ? \"SVG\" : \"VML\");\n    if (R.type == \"VML\") {\n        var d = g.doc.createElement(\"div\"),\n            b;\n        d.innerHTML = '<v:shape adj=\"1\"/>';\n        b = d.firstChild;\n        b.style.behavior = \"url(#default#VML)\";\n        if (!(b && typeof b.adj == \"object\")) {\n            return (R.type = E);\n        }\n        d = null;\n    }\n    /*\\\n     * Raphael.svg\n     [ property (boolean) ]\n     **\n     * `true` if browser supports SVG.\n    \\*/\n    /*\\\n     * Raphael.vml\n     [ property (boolean) ]\n     **\n     * `true` if browser supports VML.\n    \\*/\n    R.svg = !(R.vml = R.type == \"VML\");\n    R._Paper = Paper;\n    /*\\\n     * Raphael.fn\n     [ property (object) ]\n     **\n     * You can add your own method to the canvas. For example if you want to draw a pie chart,\n     * you can create your own pie chart function and ship it as a Raphaël plugin. To do this\n     * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a\n     * Raphaël instance is created, otherwise it will take no effect. Please note that the\n     * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to\n     * ensure any namespacing ensures proper context.\n     > Usage\n     | Raphael.fn.arrow = function (x1, y1, x2, y2, size) {\n     |     return this.path( ... );\n     | };\n     | // or create namespace\n     | Raphael.fn.mystuff = {\n     |     arrow: function () {…},\n     |     star: function () {…},\n     |     // etc…\n     | };\n     | var paper = Raphael(10, 10, 630, 480);\n     | // then use it\n     | paper.arrow(10, 10, 30, 30, 5).attr({fill: \"#f00\"});\n     | paper.mystuff.arrow();\n     | paper.mystuff.star();\n    \\*/\n    R.fn = paperproto = Paper.prototype = R.prototype;\n    R._id = 0;\n    /*\\\n     * Raphael.is\n     [ method ]\n     **\n     * Handful of replacements for `typeof` operator.\n     > Parameters\n     - o (…) any object or primitive\n     - type (string) name of the type, i.e. “string”, “function”, “number”, etc.\n     = (boolean) is given value is of given type\n    \\*/\n    R.is = function (o, type) {\n        type = lowerCase.call(type);\n        if (type == \"finite\") {\n            return !isnan[has](+o);\n        }\n        if (type == \"array\") {\n            return o instanceof Array;\n        }\n        return  (type == \"null\" && o === null) ||\n                (type == typeof o && o !== null) ||\n                (type == \"object\" && o === Object(o)) ||\n                (type == \"array\" && Array.isArray && Array.isArray(o)) ||\n                objectToString.call(o).slice(8, -1).toLowerCase() == type;\n    };\n\n    function clone(obj) {\n        if (typeof obj == \"function\" || Object(obj) !== obj) {\n            return obj;\n        }\n        var res = new obj.constructor;\n        for (var key in obj) if (obj[has](key)) {\n            res[key] = clone(obj[key]);\n        }\n        return res;\n    }\n\n    /*\\\n     * Raphael.angle\n     [ method ]\n     **\n     * Returns angle between two or three points\n     > Parameters\n     - x1 (number) x coord of first point\n     - y1 (number) y coord of first point\n     - x2 (number) x coord of second point\n     - y2 (number) y coord of second point\n     - x3 (number) #optional x coord of third point\n     - y3 (number) #optional y coord of third point\
57590n     = (number) angle in degrees.\n    \\*/\n    R.angle = function (x1, y1, x2, y2, x3, y3) {\n        if (x3 == null) {\n            var x = x1 - x2,\n                y = y1 - y2;\n            if (!x && !y) {\n                return 0;\n            }\n            return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;\n        } else {\n            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);\n        }\n    };\n    /*\\\n     * Raphael.rad\n     [ method ]\n     **\n     * Transform angle to radians\n     > Parameters\n     - deg (number) angle in degrees\n     = (number) angle in radians.\n    \\*/\n    R.rad = function (deg) {\n        return deg % 360 * PI / 180;\n    };\n    /*\\\n     * Raphael.deg\n     [ method ]\n     **\n     * Transform angle to degrees\n     > Parameters\n     - rad (number) angle in radians\n     = (number) angle in degrees.\n    \\*/\n    R.deg = function (rad) {\n        return Math.round ((rad * 180 / PI% 360)* 1000) / 1000;\n    };\n    /*\\\n     * Raphael.snapTo\n     [ method ]\n     **\n     * Snaps given value to given grid.\n     > Parameters\n     - values (array|number) given array of values or step of the grid\n     - value (number) value to adjust\n     - tolerance (number) #optional tolerance for snapping. Default is `10`.\n     = (number) adjusted value.\n    \\*/\n    R.snapTo = function (values, value, tolerance) {\n        tolerance = R.is(tolerance, \"finite\") ? tolerance : 10;\n        if (R.is(values, array)) {\n            var i = values.length;\n            while (i--) if (abs(values[i] - value) <= tolerance) {\n                return values[i];\n            }\n        } else {\n            values = +values;\n            var rem = value % values;\n            if (rem < tolerance) {\n                return value - rem;\n            }\n            if (rem > values - tolerance) {\n                return value - rem + values;\n            }\n        }\n        return value;\n    };\n\n    /*\\\n     * Raphael.createUUID\n     [ method ]\n     **\n     * Returns RFC4122, version 4 ID\n    \\*/\n    var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {\n        return function () {\n            return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(uuidRegEx, uuidReplacer).toUpperCase();\n        };\n    })(/[xy]/g, function (c) {\n        var r = math.random() * 16 | 0,\n            v = c == \"x\" ? r : (r & 3 | 8);\n        return v.toString(16);\n    });\n\n    /*\\\n     * Raphael.setWindow\n     [ method ]\n     **\n     * Used when you need to draw in `&lt;iframe>`. Switched window to the iframe one.\n     > Parameters\n     - newwin (window) new window object\n    \\*/\n    R.setWindow = function (newwin) {\n        eve(\"raphael.setWindow\", R, g.win, newwin);\n        g.win = newwin;\n        g.doc = g.win.document;\n        if (R._engine.initWin) {\n            R._engine.initWin(g.win);\n        }\n    };\n    var toHex = function (color) {\n        if (R.vml) {\n            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/\n            var trim = /^\\s+|\\s+$/g;\n            var bod;\n            try {\n                var docum = new ActiveXObject(\"htmlfile\");\n                docum.write(\"<body>\");\n                docum.close();\n                bod = docum.body;\n            } catch(e) {\n                bod = createPopup().document.body;\n            }\n            var range = bod.createTextRange();\n            toHex = cacher(function (color) {\n                try {\n                    bod.style.color = Str(color).replace(trim, E);\n                    var value = range.queryCommandValue(\"ForeColor\");\n                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);\n                    return \"#\" + (\"000000\" + value.toString(16)).slice(-6);\n                } catch(e) {\n                    return \"none\";\n                }\n            });\n        } else {\n            var i = g.doc.createElement(\"i\");\n            i.title = \"Rapha\\xebl Colour Picker\";\n            i.style.display = \"none\";\n            g.doc.body.appendChild(i);
57590\n            toHex = cacher(function (color) {\n                i.style.color = color;\n                return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue(\"color\");\n            });\n        }\n        return toHex(color);\n    },\n    hsbtoString = function () {\n        return \"hsb(\" + [this.h, this.s, this.b] + \")\";\n    },\n    hsltoString = function () {\n        return \"hsl(\" + [this.h, this.s, this.l] + \")\";\n    },\n    rgbtoString = function () {\n        return this.hex;\n    },\n    prepareRGB = function (r, g, b) {\n        if (g == null && R.is(r, \"object\") && \"r\" in r && \"g\" in r && \"b\" in r) {\n            b = r.b;\n            g = r.g;\n            r = r.r;\n        }\n        if (g == null && R.is(r, string)) {\n            var clr = R.getRGB(r);\n            r = clr.r;\n            g = clr.g;\n            b = clr.b;\n        }\n        if (r > 1 || g > 1 || b > 1) {\n            r /= 255;\n            g /= 255;\n            b /= 255;\n        }\n\n        return [r, g, b];\n    },\n    packageRGB = function (r, g, b, o) {\n        r *= 255;\n        g *= 255;\n        b *= 255;\n        var rgb = {\n            r: r,\n            g: g,\n            b: b,\n            hex: R.rgb(r, g, b),\n            toString: rgbtoString\n        };\n        R.is(o, \"finite\") && (rgb.opacity = o);\n        return rgb;\n    };\n\n    /*\\\n     * Raphael.color\n     [ method ]\n     **\n     * Parses the color string and returns object with all values for the given color.\n     > Parameters\n     - clr (string) color string in one of the supported formats (see @Raphael.getRGB)\n     = (object) Combined RGB & HSB object in format:\n     o {\n     o     r (number) red,\n     o     g (number) green,\n     o     b (number) blue,\n     o     hex (string) color in HTML/CSS format: #••••••,\n     o     error (boolean) `true` if string can’t be parsed,\n     o     h (number) hue,\n     o     s (number) saturation,\n     o     v (number) value (brightness),\n     o     l (number) lightness\n     o }\n    \\*/\n    R.color = function (clr) {\n        var rgb;\n        if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"b\" in clr) {\n            rgb = R.hsb2rgb(clr);\n            clr.r = rgb.r;\n            clr.g = rgb.g;\n            clr.b = rgb.b;\n            clr.hex = rgb.hex;\n        } else if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"l\" in clr) {\n            rgb = R.hsl2rgb(clr);\n            clr.r = rgb.r;\n            clr.g = rgb.g;\n            clr.b = rgb.b;\n            clr.hex = rgb.hex;\n        } else {\n            if (R.is(clr, \"string\")) {\n                clr = R.getRGB(clr);\n            }\n            if (R.is(clr, \"object\") && \"r\" in clr && \"g\" in clr && \"b\" in clr) {\n                rgb = R.rgb2hsl(clr);\n                clr.h = rgb.h;\n                clr.s = rgb.s;\n                clr.l = rgb.l;\n                rgb = R.rgb2hsb(clr);\n                clr.v = rgb.b;\n            } else {\n                clr = {hex: \"none\"};\n                clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;\n            }\n        }\n        clr.toString = rgbtoString;\n        return clr;\n    };\n    /*\\\n     * Raphael.hsb2rgb\n     [ method ]\n     **\n     * Converts HSB values to RGB object.\n     > Parameters\n     - h (number) hue\n     - s (number) saturation\n     - v (number) value or brightness\n     = (object) RGB object in format:\n     o {\n     o     r (number) red,\n     o     g (number) green,\n     o     b (number) blue,\n     o     hex (string) color in HTML/CSS format: #••••••\n     o }\n    \\*/\n    R.hsb2rgb = function (h, s, v, o) {\n        if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"b\" in h) {\n            v = h.b;\n            s = h.s;\n            o = h.o;\n            h = h.h;\n        }\n        h *= 360;\n        var R, G, B, X, C;\n        h = (h % 360) / 60;\n        C = v * s;\n        X = C * (1 - abs(h % 2 - 1));\n        R = G = B = v - C;\n\n        h = ~~h;\n        R += [C, X, 0, 0, X, C][h];\n        G += [X, C, C, X, 0, 0][h];\n        B += [0, 0, X, C, C, X][h];\n        return packageRGB(R, G, B, o);\n    };\n    /*\\\n     * Raphael.hsl2rgb\n     [ method ]\n     **\n     * Converts HSL values to RGB object.\n     > Parameters\n     - h (number) hue\n     - s (number) saturation\n     - l (number) luminosity\n     = (object) RGB object in format:\n     o {\n     o     r (number) red,\n     o     g (number) green,\n     o     b (number) blue,\n     o     hex (string) color in HTML/CSS format: #••••••\n     o }\n    \\*/\n    R.hsl2rgb = function (h, s, l, o) {\n        if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"l\" in h) {\n            l = h.l;\n            s = h.s;\n            h = h.h;\n        }\n        if (h > 1 || s > 1 || l > 1) {\n            h /= 360;\n            s /= 100;\n            l /= 100;\n        }\n        h *= 360;\n        var R, G, B, X, C;\n        h = (h % 360) / 60;\n        C = 2 * s * (l < .5 ? l : 1 - l);\n        X = C * (1 - abs(h % 2 - 1));\n        R = G = B = l - C / 2;\n\n        h = ~~h;\n        R += [C, X, 0, 0, X, C][h];\n        G += [X, C, C, X, 0, 0][h];\n        B += [0, 0, X, C, C, X][h];\n        return packageRGB(R, G, B, o);\n    };\n    /*\\\n     * Raphael.rgb2hsb\n     [ method ]\n     **\n     * Converts RGB values to HSB object.\n     > Parameters\n     - r (number) red\n     - g (number) green\n     - b (number) blue\n     = (object) HSB object in format:\n     o {\n     o     h (number) hue\n     o     s (number) saturation\n     o     b (number) brightness\n     o }\n    \\*/\n    R.rgb2hsb = function (r, g, b) {\n        b = prepareRGB(r, g, b);\n        r = b[0];\n        g = b[1];\n        b = b[2];\n\n        var H, S, V, C;\n        V = mmax(r, g, b);\n        C = V - mmin(r, g, b);\n        H = (C == 0 ? null :\n             V == r ? (g - b) / C :\n             V == g ? (b - r) / C + 2 :\n                      (r - g) / C + 4\n            );\n        H = ((H + 360) % 6) * 60 / 360;\n        S = C == 0 ? 0 : C / V;\n        return {h: H, s: S, b: V, toString: hsbtoString};\n    };\n    /*\\\n     * Raphael.rgb2hsl\n     [ method ]\n     **\n     * Converts RGB values to HSL object.\n     > Parameters\n     - r (number) red\n     - g (number) green\n     - b (number) blue\n     = (object) HSL object in format:\n     o {\n     o     h (number) hue\n     o     s (number) saturation\n     o     l (number) luminosity\n     o }\n    \\*/\n    R.rgb2hsl = function (r, g, b) {\n        b = prepareRGB(r, g, b);\n        r = b[0];\n        g = b[1];\n        b = b[2];\n\n        var H, S, L, M, m, C;\n        M = mmax(r, g, b);\n        m = mmin(r, g, b);\n        C = M - m;\n        H = (C == 0 ? null :\n             M == r ? (g - b) / C :\n             M == g ? (b - r) / C + 2 :\n                      (r - g) / C + 4);\n        H = ((H + 360) % 6) * 60 / 360;\n        L = (M + m) / 2;\n        S = (C == 0 ? 0 :\n             L < .5 ? C / (2 * L) :\n                      C / (2 - 2 * L));\n        return {h: H, s: S, l: L, toString: hsltoString};\n    };\n    R._path2string = function () {\n        return this.join(\",\").replace(p2s, \"$1\");\n    };\n    function repush(array, item) {\n        for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {\n            return array.push(array.splice(i, 1)[0]);\n        }\n    }\n    function cacher(f, scope, postprocessor) {\n        function newf() {\n            var arg = Array.prototype.slice.call(arguments, 0),\n                args = arg.join(\"\\u2400\"),\n                cache = newf.cache = newf.cache || {},\n                count = newf.count = newf.count || [];\n            if (cache[has](args)) {\n                repush(count, args);\n                return postprocessor ? postprocessor(cache[args]) : cache[args];\n            }\n            count.length >= 1e3 && delete cache[count.shift()];\n            count.push(args);\n            cache[args] = f[apply](scope, arg);\n            return postprocessor ? postprocessor(cache[args]) : cache[args];\n        }\n        return newf;\n    }\n\n    var preload = R._preload = function (src, f) {\n        var img = g.doc.createElement(\"img\");\n        img.style.cssText = \"position:absolute;
57590left:-9999em;top:-9999em\";\n        img.onload = function () {\n            f.call(this);\n            this.onload = null;\n            g.doc.body.removeChild(this);\n        };\n        img.onerror = function () {\n            g.doc.body.removeChild(this);\n        };\n        g.doc.body.appendChild(img);\n        img.src = src;\n    };\n\n    function clrToString() {\n        return this.hex;\n    }\n\n    /*\\\n     * Raphael.getRGB\n     [ method ]\n     **\n     * Parses colour string as RGB object\n     > Parameters\n     - colour (string) colour string in one of formats:\n     # <ul>\n     #     <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>\n     #     <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>\n     #     <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>\n     #     <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>\n     #     <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>\n     #     <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>\n     #     <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>\n     #     <li>hsl(•••, •••, •••) — same as hsb</li>\n     #     <li>hsl(•••%, •••%, •••%) — same as hsb</li>\n     # </ul>\n     = (object) RGB object in format:\n     o {\n     o     r (number) red,\n     o     g (number) green,\n     o     b (number) blue\n     o     hex (string) color in HTML/CSS format: #••••••,\n     o     error (boolean) true if string can’t be parsed\n     o }\n    \\*/\n    R.getRGB = cacher(function (colour) {\n        if (!colour || !!((colour = Str(colour)).indexOf(\"-\") + 1)) {\n            return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n        }\n        if (colour == \"none\") {\n            return {r: -1, g: -1, b: -1, hex: \"none\", toString: clrToString};\n        }\n        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == \"#\") && (colour = toHex(colour));\n        var res,\n            red,\n            green,\n            blue,\n            opacity,\n            t,\n            values,\n            rgb = colour.match(colourRegExp);\n        if (rgb) {\n            if (rgb[2]) {\n                blue = toInt(rgb[2].substring(5), 16);\n                green = toInt(rgb[2].substring(3, 5), 16);\n                red = toInt(rgb[2].substring(1, 3), 16);\n            }\n            if (rgb[3]) {\n                blue = toInt((t = rgb[3].charAt(3)) + t, 16);\n                green = toInt((t = rgb[3].charAt(2)) + t, 16);\n                red = toInt((t = rgb[3].charAt(1)) + t, 16);\n            }\n            if (rgb[4]) {\n                values = rgb[4][split](commaSpaces);\n                red = toFloat(values[0]);\n                values[0].slice(-1) == \"%\" && (red *= 2.55);\n                green = toFloat(values[1]);\n                values[1].slice(-1) == \"%\" && (green *= 2.55);\n                blue = toFloat(values[2]);\n                values[2].slice(-1) == \"%\" && (blue *= 2.55);\n                rgb[1].toLowerCase().slice(0, 4) == \"rgba\" && (opacity = toFloat(values[3]));\n                values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n            }\n            if (rgb[5]) {\n                values = rgb[5][split](commaSpaces);\n                red = toFloat(values[0]);\n                values[0].slice(-1) == \"%\" && (red *= 2.55);\n                green = toFloat(values[1]);\n                values[1].slice(-1) == \"%\" && (green *= 2.55);\n                blue = toFloat(values[2]);\n                values[2].slice(-1) == \"%\" && (blue *= 2.55);\n                (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n                rgb[1].toLowerCase().slice(0, 4) == \"hsba\" && (opacity = toFloat(values[3]));\n                values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n                return R.hsb2rgb(red, green, blue, opacity);\n            }\n            if (rgb[6]) {\n                values = rgb[6][split](commaSpaces);\n                red = toFloat(values[0]);\n                values[0].slice(-1) == \"%\" && (red *= 2.55);\n                green = toFloat(values[1]);\n                values[1].slice(-1) == \"%\" && (green *= 2.55);\n                blue = toFloat(values[2]);\n                values[2].slice(-1) == \"%\" && (blue *= 2.55);\n                (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n                rgb[1].toLowerCase().slice(0, 4) == \"hsla\" && (opacity = toFloat(values[3]));\n                values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n                return R.hsl2rgb(red, green, blue, opacity);\n            }\n            rgb = {r: red, g: green, b: blue, toString: clrToString};\n            rgb.hex = \"#\" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);\n            R.is(opacity, \"finite\") && (rgb.opacity = opacity);\n            return rgb;\n        }\n        return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n    }, R);\n    /*\\\n     * Raphael.hsb\n     [ method ]\n     **\n     * Converts HSB values to hex representation of the colour.\n     > Parameters\n     - h (number) hue\n     - s (number) saturation\n     - b (number) value or brightness\n     = (string) hex representation of the colour.\n    \\*/\n    R.hsb = cacher(function (h, s, b) {\n        return R.hsb2rgb(h, s, b).hex;\n    });\n    /*\\\n     * Raphael.hsl\n     [ method ]\n     **\n     * Converts HSL values to hex representation of the colour.\n     > Parameters\n     - h (number) hue\n     - s (number) saturation\n     - l (number) luminosity\n     = (string) hex representation of the colour.\n    \\*/\n    R.hsl = cacher(function (h, s, l) {\n        return R.hsl2rgb(h, s, l).hex;\n    });\n    /*\\\n     * Raphael.rgb\n     [ method ]\n     **\n     * Converts RGB values to hex representation of the colour.\n     > Parameters\n     - r (number) red\n     - g (number) green\n     - b (number) blue\n     = (string) hex representation of the colour.\n    \\*/\n    R.rgb = cacher(function (r, g, b) {\n        function round(x) { return (x + 0.5) | 0; }\n        return \"#\" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);\n    });\n    /*\\\n     * Raphael.getColor\n     [ method ]\n     **\n     * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset\n     > Parameters\n     - value (number) #optional brightness, default is `0.75`\n     = (string) hex representation of the colour.\n    \\*/\n    R.getColor = function (value) {\n        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},\n            rgb = this.hsb2rgb(start.h, start.s, start.b);\n        start.h += .075;\n        if (start.h > 1) {\n            start.h = 0;\n            start.s -= .2;\n            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});\n        }\n        return rgb.hex;\n    };\n    /*\\\n     * Raphael.getColor.reset\n     [ method ]\n     **\n     * Resets spectrum position for @Raphael.getColor back to red.\n    \\*/\n    R.getColor.reset = function () {\n        delete this.start;\n    };\n\n    // http://schepers.cc/getting-to-the-point\n    function catmullRom2bezier(crp, z) {\n        var d = [];\n        for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {\n            var p = [\n                        {x: +crp[i - 2], y: +crp[i - 1]},\n                        {x: +crp[i],     y: +crp[i + 1]},\n                        {x: +crp[i + 2], y: +crp[i + 3]},\n                        {x: +crp[i + 4], y: +crp[i + 5]}\n                    ];\n            if (z) {\n                if (!i) {\n                    p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};\n                } else if (iLen - 4 == i) {\n                    p[3] = {x: +crp[0], y: +crp[1]};\n                }
57590 else if (iLen - 2 == i) {\n                    p[2] = {x: +crp[0], y: +crp[1]};\n                    p[3] = {x: +crp[2], y: +crp[3]};\n                }\n            } else {\n                if (iLen - 4 == i) {\n                    p[3] = p[2];\n                } else if (!i) {\n                    p[0] = {x: +crp[i], y: +crp[i + 1]};\n                }\n            }\n            d.push([\"C\",\n                  (-p[0].x + 6 * p[1].x + p[2].x) / 6,\n                  (-p[0].y + 6 * p[1].y + p[2].y) / 6,\n                  (p[1].x + 6 * p[2].x - p[3].x) / 6,\n                  (p[1].y + 6*p[2].y - p[3].y) / 6,\n                  p[2].x,\n                  p[2].y\n            ]);\n        }\n\n        return d;\n    }\n    /*\\\n     * Raphael.parsePathString\n     [ method ]\n     **\n     * Utility method\n     **\n     * Parses given path string into an array of arrays of path segments.\n     > Parameters\n     - pathString (string|array) path string or array of segments (in the last case it will be returned straight away)\n     = (array) array of segments.\n    \\*/\n    R.parsePathString = function (pathString) {\n        if (!pathString) {\n            return null;\n        }\n        var pth = paths(pathString);\n        if (pth.arr) {\n            return pathClone(pth.arr);\n        }\n\n        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},\n            data = [];\n        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption\n            data = pathClone(pathString);\n        }\n        if (!data.length) {\n            Str(pathString).replace(pathCommand, function (a, b, c) {\n                var params = [],\n                    name = b.toLowerCase();\n                c.replace(pathValues, function (a, b) {\n                    b && params.push(+b);\n                });\n                if (name == \"m\" && params.length > 2) {\n                    data.push([b][concat](params.splice(0, 2)));\n                    name = \"l\";\n                    b = b == \"m\" ? \"l\" : \"L\";\n                }\n                if (name == \"r\") {\n                    data.push([b][concat](params));\n                } else while (params.length >= paramCounts[name]) {\n                    data.push([b][concat](params.splice(0, paramCounts[name])));\n                    if (!paramCounts[name]) {\n                        break;\n                    }\n                }\n            });\n        }\n        data.toString = R._path2string;\n        pth.arr = pathClone(data);\n        return data;\n    };\n    /*\\\n     * Raphael.parseTransformString\n     [ method ]\n     **\n     * Utility method\n     **\n     * Parses given path string into an array of transformations.\n     > Parameters\n     - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)\n     = (array) array of transformations.\n    \\*/\n    R.parseTransformString = cacher(function (TString) {\n        if (!TString) {\n            return null;\n        }\n        var paramCounts = {r: 3, s: 4, t: 2, m: 6},\n            data = [];\n        if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption\n            data = pathClone(TString);\n        }\n        if (!data.length) {\n            Str(TString).replace(tCommand, function (a, b, c) {\n                var params = [],\n                    name = lowerCase.call(b);\n                c.replace(pathValues, function (a, b) {\n                    b && params.push(+b);\n                });\n                data.push([b][concat](params));\n            });\n        }\n        data.toString = R._path2string;\n        return data;\n    }, this, function(elem) {\n        if (!elem) return elem;\n        var newData = [];\n        for (var i = 0; i < elem.length; i++) {\n            var newLevel = [];\n            for (var j = 0; j < elem[i].length; j++) {\n                newLevel.push(elem[i][j]);\n            }\n            newData.push(newLevel);\n        }\n      return newData; } );\n    // PATHS\n    var paths = function (ps) {\n        var p = paths.ps = paths.ps || {};\n        if (p[ps]) {\n            p[ps].sleep = 100;\n        } else {\n            p[ps] = {\n                sleep: 100\n            };\n        }\n        setTimeout(function () {\n            for (var key in p) if (p[has](key) && key != ps) {\n                p[key].sleep--;\n                !p[key].sleep && delete p[key];\n            }\n        });\n        return p[ps];\n    };\n    /*\\\n     * Raphael.findDotsAtSegment\n     [ method ]\n     **\n     * Utility method\n     **\n     * Find dot coordinates on the given cubic bezier curve at the given t.\n     > Parameters\n     - p1x (number) x of the first point of the curve\
57590n     - p1y (number) y of the first point of the curve\n     - c1x (number) x of the first anchor of the curve\n     - c1y (number) y of the first anchor of the curve\n     - c2x (number) x of the second anchor of the curve\n     - c2y (number) y of the second anchor of the curve\n     - p2x (number) x of the second point of the curve\n     - p2y (number) y of the second point of the curve\n     - t (number) position on the curve (0..1)\n     = (object) point information in format:\n     o {\n     o     x: (number) x coordinate of the point\n     o     y: (number) y coordinate of the point\n     o     m: {\n     o         x: (number) x coordinate of the left anchor\n     o         y: (number) y coordinate of the left anchor\n     o     }\n     o     n: {\n     o         x: (number) x coordinate of the right anchor\n     o         y: (number) y coordinate of the right anchor\n     o     }\n     o     start: {\n     o         x: (number) x coordinate of the start of the curve\n     o         y: (number) y coordinate of the start of the curve\n     o     }\n     o     end: {\n     o         x: (number) x coordinate of the end of the curve\n     o         y: (number) y coordinate of the end of the curve\n     o     }\n     o     alpha: (number) angle of the curve derivative at the point\n     o }\n    \\*/\n    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n        var t1 = 1 - t,\n            t13 = pow(t1, 3),\n            t12 = pow(t1, 2),\n            t2 = t * t,\n            t3 = t2 * t,\n            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,\n            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,\n            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),\n            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),\n            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),\n            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),\n            ax = t1 * p1x + t * c1x,\n            ay = t1 * p1y + t * c1y,\n            cx = t1 * c2x + t * p2x,\n            cy = t1 * c2y + t * p2y,\n            alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);\n        (mx > nx || my < ny) && (alpha += 180);\n        return {\n            x: x,\n            y: y,\n            m: {x: mx, y: my},\n            n: {x: nx, y: ny},\n            start: {x: ax, y: ay},\n            end: {x: cx, y: cy},\n            alpha: alpha\n        };\n    };\n    /*\\\n     * Raphael.bezierBBox\n     [ method ]\n     **\n     * Utility method\n     **\n     * Return bounding box of a given cubic bezier curve\n     > Parameters\n     - p1x (number) x of the first point of the curve\n     - p1y (number) y of the first point of the curve\n     - c1x (number) x of the first anchor of the curve\n     - c1y (number) y of the first anchor of the curve\n     - c2x (number) x of the second anchor of the curve\n     - c2y (number) y of the second anchor of the curve\n     - p2x (number) x of the second point of the curve\n     - p2y (number) y of the second point of the curve\n     * or\n     - bez (array) array of six points for bezier curve\n     = (object) point information in format:\n     o {\n     o     min: {\n     o         x: (number) x coordinate of the left point\n     o         y: (number) y coordinate of the top point\n     o     }\n     o     max: {\n     o         x: (number) x coordinate of the right point\n     o         y: (number) y coordinate of the bottom point\n     o     }\n     o }\n    \\*/\n    R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n        if (!R.is(p1x, \"array\")) {\n            p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];\n        }\n        var bbox = curveDim.apply(null, p1x);\n        return {\n            x: bbox.min.x,\n            y: bbox.min.y,\n            x2: bbox.max.x,\n            y2: bbox.max.y,\n            width: bbox.max.x - bbox.min.x,\n            height: bbox.max.y - bbox.min.y\n        };\n    };\n    /*\\\n     * Raphael.isPointInsideBBox\n     [ method ]\n     **\n     * Utility method\n     **\n     * Returns `true` if given point is inside bounding boxes.\n     > Parameters\n     - bbox (string) bounding box\n     - x (string) x coordinate of the point\n     - y (string) y co
57590ordinate of the point\n     = (boolean) `true` if point inside\n    \\*/\n    R.isPointInsideBBox = function (bbox, x, y) {\n        return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;\n    };\n    /*\\\n     * Raphael.isBBoxIntersect\n     [ method ]\n     **\n     * Utility method\n     **\n     * Returns `true` if two bounding boxes intersect\n     > Parameters\n     - bbox1 (string) first bounding box\n     - bbox2 (string) second bounding box\n     = (boolean) `true` if they intersect\n    \\*/\n    R.isBBoxIntersect = function (bbox1, bbox2) {\n        var i = R.isPointInsideBBox;\n        return i(bbox2, bbox1.x, bbox1.y)\n            || i(bbox2, bbox1.x2, bbox1.y)\n            || i(bbox2, bbox1.x, bbox1.y2)\n            || i(bbox2, bbox1.x2, bbox1.y2)\n            || i(bbox1, bbox2.x, bbox2.y)\n            || i(bbox1, bbox2.x2, bbox2.y)\n            || i(bbox1, bbox2.x, bbox2.y2)\n            || i(bbox1, bbox2.x2, bbox2.y2)\n            || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)\n            && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);\n    };\n    function base3(t, p1, p2, p3, p4) {\n        var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,\n            t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;\n        return t * t2 - 3 * p1 + 3 * p2;\n    }\n    function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {\n        if (z == null) {\n            z = 1;\n        }\n        z = z > 1 ? 1 : z < 0 ? 0 : z;\n        var z2 = z / 2,\n            n = 12,\n            Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],\n            Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],\n            sum = 0;\n        for (var i = 0; i < n; i++) {\n            var ct = z2 * Tvalues[i] + z2,\n                xbase = base3(ct, x1, x2, x3, x4),\n                ybase = base3(ct, y1, y2, y3, y4),\n                comb = xbase * xbase + ybase * ybase;\n            sum += Cvalues[i] * math.sqrt(comb);\n        }\n        return z2 * sum;\n    }\n    function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {\n        if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {\n            return;\n        }\n        var t = 1,\n            step = t / 2,\n            t2 = t - step,\n            l,\n            e = .01;\n        l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n        while (abs(l - ll) > e) {\n            step /= 2;\n            t2 += (l < ll ? 1 : -1) * step;\n            l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n        }\n        return t2;\n    }\n    function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {\n        if (\n            mmax(x1, x2) < mmin(x3, x4) ||\n            mmin(x1, x2) > mmax(x3, x4) ||\n            mmax(y1, y2) < mmin(y3, y4) ||\n            mmin(y1, y2) > mmax(y3, y4)\n        ) {\n            return;\n        }\n        var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),\n            ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),\n            denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);\n\n        if (!denominator) {\n            return;\n        }\n        var px = nx / denominator,\n            py = ny / denominator,\n            px2 = +px.toFixed(2),\n            py2 = +py.toFixed(2);\n        if (\n            px2 < +mmin(x1, x2).toFixed(2) ||\n            px2 > +mmax(x1, x2).toFixed(2) ||\n            px2 < +mmin(x3, x4).toFixed(2) ||\n            px2 > +mmax(x3, x4).toFixed(2) ||\n            py2 < +mmin(y1, y2).toFixed(2) ||\n            py2 > +mmax(y1, y2).toFixed(2) ||\n            py2 < +mmin(y3, y4).toFixed(2) ||\n            py2 > +mmax(y3, y4).toFixed(2)\n        ) {\n            return;\n        }\n        return {x: px, y: py};\n    }\n    function inter(bez1, bez2) {\n        return interHelper(bez1, bez2);\n    }\n    function interCount(bez1, bez2) {\n        return interHelper(bez1, bez2, 1);\n    }\n    function interHelper(bez1, bez2, justCount) {\n        var bbox1 = R.bezierBBox(bez1),\n            bbox2 = R.bezierBBox(bez2);\n        if (!R.isBBoxIntersect(bbox1, bbox2)) {\n            return justCount ? 0 : [];\n        }\n        var l1 = bezlen.apply(0, bez1),\n            l2 = bezlen.apply(0, bez2),\n            n1 = mmax(~~(l1 / 5), 1),\
57590n            n2 = mmax(~~(l2 / 5), 1),\n            dots1 = [],\n            dots2 = [],\n            xy = {},\n            res = justCount ? 0 : [];\n        for (var i = 0; i < n1 + 1; i++) {\n            var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));\n            dots1.push({x: p.x, y: p.y, t: i / n1});\n        }\n        for (i = 0; i < n2 + 1; i++) {\n            p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));\n            dots2.push({x: p.x, y: p.y, t: i / n2});\n        }\n        for (i = 0; i < n1; i++) {\n            for (var j = 0; j < n2; j++) {\n                var di = dots1[i],\n                    di1 = dots1[i + 1],\n                    dj = dots2[j],\n                    dj1 = dots2[j + 1],\n                    ci = abs(di1.x - di.x) < .001 ? \"y\" : \"x\",\n                    cj = abs(dj1.x - dj.x) < .001 ? \"y\" : \"x\",\n                    is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);\n                if (is) {\n                    if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {\n                        continue;\n                    }\n                    xy[is.x.toFixed(4)] = is.y.toFixed(4);\n                    var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),\n                        t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);\n                    if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {\n                        if (justCount) {\n                            res++;\n                        } else {\n                            res.push({\n                                x: is.x,\n                                y: is.y,\n                                t1: mmin(t1, 1),\n                                t2: mmin(t2, 1)\n                            });\n                        }\n                    }\n                }\n            }\n        }\n        return res;\n    }\n    /*\\\n     * Raphael.pathIntersection\n     [ method ]\n     **\n     * Utility method\n     **\n     * Finds intersections of two paths\n     > Parameters\n     - path1 (string) path string\n     - path2 (string) path string\n     = (array) dots of intersection\n     o [\n     o     {\n     o         x: (number) x coordinate of the point\n     o         y: (number) y coordinate of the point\n     o         t1: (number) t value for segment of path1\n     o         t2: (number) t value for segment of path2\n     o         segment1: (number) order number for segment of path1\n     o         segment2: (number) order number for segment of path2\n     o         bez1: (array) eight coordinates representing beziér curve for the segment of path1\n     o         bez2: (array) eight coordinates representing beziér curve for the segment of path2\n     o     }\n     o ]\n    \\*/\n    R.pathIntersection = function (path1, path2) {\n        return interPathHelper(path1, path2);\n    };\n    R.pathIntersectionNumber = function (path1, path2) {\n        return interPathHelper(path1, path2, 1);\n    };\n    function interPathHelper(path1, path2, justCount) {\n        path1 = R._path2curve(path1);\n        path2 = R._path2curve(path2);\n        var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,\n            res = justCount ? 0 : [];\n        for (var i = 0, ii = path1.length; i < ii; i++) {\n            var pi = path1[i];\n            if (pi[0] == \"M\") {\n                x1 = x1m = pi[1];\n                y1 = y1m = pi[2];\n            } else {\n                if (pi[0] == \"C\") {\n                    bez1 = [x1, y1].concat(pi.slice(1));\n                    x1 = bez1[6];\n                    y1 = bez1[7];\n                } else {\n                    bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];\n                    x1 = x1m;\n                    y1 = y1m;\n                }\n                for (var j = 0, jj = path2.length; j < jj; j++) {\n                    var pj = path2[j];\n                    if (pj[0] == \"M\") {\n                        x2 = x2m = pj[1];\n                        y2 = y2m = pj[2];\n                    } else {\n                        if (pj[0] == \"C\") {\n                            bez2 = [x2, y2].concat(pj.slice(1));\n                            x2 = bez2[6];\n                            y2 = bez2[7];\n                        } else {\n                            bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];\n                            x2 = x2m;\n                            y2 = y2m;\n                        }\n                        var intr = interHelper(bez1, bez2, justCount);\n                        if (justCount) {\n                            res += intr;\n                        } else {\n                            for (var k = 0, kk = intr.length; k < kk; k++) {\n                                intr[k].segment1 = i;\n                                intr[k].segment2 = j;\n                                intr[k].bez1 = bez1;\n                                intr[k].bez2 = bez2;\n                            }\n                            res = res.concat(intr);\n                        }\n                    }\n                }\n            }\n        }\n        return res;\n    }\n    /*\\\n     * Raphael.isPointInsidePath\n     [ method ]\n     **\n     * Utility method\n     **\n     * Returns `true` if given point is inside a given closed path.\n     > Parameters\n     - path (string) path string\n     - x (number) x of the point\n     - y (number) y of the point\n     = (boolean) true, if point is inside the path\n    \\*/\n    R.isPointInsidePath = function (path, x, y) {\n        var bbox = R.pathBBox(path);\n        return R.isPointInsideBBox(bbox, x, y) &&\n               interPathHelper(path, [[\"M\", x, y], [\"H\", bbox.x2 + 10]], 1) % 2 == 1;\n    };\n    R._removedFactory = function (methodname) {\n        return function () {\n            eve(\"raphael.log\", null, \"Rapha\\xebl: you are calling to method \\u201c\" + methodname + \"\\u201d of removed object\", methodname);\n        };\n    };\n    /*\\\n     * Raphael.pathBBox\n     [ method ]\n     **\n     * Utility method\n     **\n     * Return bounding box of a given path\n     > Parameters\n     - path (string) path string\n     = (object) bounding box\n     o {\n     o     x: (number) x coordinate of the left top point of the box\n     o     y: (number) y coordinate of the left top point of the box\n     o     x2: (number) x coordinate of the right bottom point of the box\n     o     y2: (number) y coordinate of the right bottom point of the box\n     o     width: (number) width of the box\n     o     height: (number) height of the box\n     o     cx: (number) x coordinate of the center of the box\n     o     cy: (number) y coordinate of the center of the box\n     o }\n    \\*/\n    var pathDimensions = R.pathBBox = function (path) {\n        var pth = paths(path);\n        if (pth.bbox) {\n            return clone(pth.bbox);\n        }\n        if (!path) {\n            return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};\n        }\n        path = path2curve(path);\n        var x = 0,\n            y = 0,\n            X = [],\n            Y = [],\n            p;\n        for (var i = 0, ii = path.length; i < ii;
57590 i++) {\n            p = path[i];\n            if (p[0] == \"M\") {\n                x = p[1];\n                y = p[2];\n                X.push(x);\n                Y.push(y);\n            } else {\n                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n                X = X[concat](dim.min.x, dim.max.x);\n                Y = Y[concat](dim.min.y, dim.max.y);\n                x = p[5];\n                y = p[6];\n            }\n        }\n        var xmin = mmin[apply](0, X),\n            ymin = mmin[apply](0, Y),\n            xmax = mmax[apply](0, X),\n            ymax = mmax[apply](0, Y),\n            width = xmax - xmin,\n            height = ymax - ymin,\n                bb = {\n                x: xmin,\n                y: ymin,\n                x2: xmax,\n                y2: ymax,\n                width: width,\n                height: height,\n                cx: xmin + width / 2,\n                cy: ymin + height / 2\n            };\n        pth.bbox = clone(bb);\n        return bb;\n    },\n        pathClone = function (pathArray) {\n            var res = clone(pathArray);\n            res.toString = R._path2string;\n            return res;\n        },\n        pathToRelative = R._pathToRelative = function (pathArray) {\n            var pth = paths(pathArray);\n            if (pth.rel) {\n                return pathClone(pth.rel);\n            }\n            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n                pathArray = R.parsePathString(pathArray);\n            }\n            var res = [],\n                x = 0,\n                y = 0,\n                mx = 0,\n                my = 0,\n                start = 0;\n            if (pathArray[0][0] == \"M\") {\n                x = pathArray[0][1];\n                y = pathArray[0][2];\n                mx = x;\n                my = y;\n                start++;\n                res.push([\"M\", x, y]);\n            }\n            for (var i = start, ii = pathArray.length; i < ii; i++) {\n                var r = res[i] = [],\n                    pa = pathArray[i];\n                if (pa[0] != lowerCase.call(pa[0])) {\n                    r[0] = lowerCase.call(pa[0]);\n                    switch (r[0]) {\n                        case \"a\":\n                            r[1] = pa[1];\n                            r[2] = pa[2];\n                            r[3] = pa[3];\n                            r[4] = pa[4];\n                            r[5] = pa[5];\n                            r[6] = +(pa[6] - x).toFixed(3);\n                            r[7] = +(pa[7] - y).toFixed(3);\n                            break;\n                        case \"v\":\n                            r[1] = +(pa[1] - y).toFixed(3);\n                            break;\n                        case \"m\":\n                            mx = pa[1];\n                            my = pa[2];\n                        default:\n                            for (var j = 1, jj = pa.length; j < jj; j++) {\n                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);\n                            }\n                    }\n                } else {\n                    r = res[i] = [];\n                    if (pa[0] == \"m\") {\n                        mx = pa[1] + x;\n                        my = pa[2] + y;\n                    }\n                    for (var k = 0, kk = pa.length; k < kk; k++) {\n                        res[i][k] = pa[k];\n                    }\n                }\n                var len = res[i].length;\n                switch (res[i][0]) {\n                    case \"z\":\n                        x = mx;\n                        y = my;\n                        break;\n                    case \"h\":\n                        x += +res[i][len - 1];\n                        break;\n                    case \"v\":\n                        y += +res[i][len - 1];\n                        break;\n                    default:\n                        x += +res[i][len - 2];\n                        y += +res[i][len - 1];\n                }\n            }\n            res.toString = R._path2string;\n            pth.rel = pathClone(res);\n            return res;\n        },\n        pathToAbsolute = R._pathToAbsolute = function (pathArray) {\n            var pth = paths(pathArray);\n            if (pth.abs) {\n                return pathClone(pth.abs);\n            }\n            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n                pathArray = R.parsePathString(pathArray);\n            }\n            if (!pathArray || !pathArray.length) {\n                return [[\"M\", 0, 0]];\n            }\n            var res = [],\n                x = 0,\n                y = 0,\n                mx = 0,\n                my = 0,\n                start = 0;\n            if (pathArray[0][0] == \"M\") {\n                x = +pathArray[0][1];\n                y = +pathArray[0][2];\n                mx = x;\n                my = y;\n                start++;\n                res[0] = [\"M\", x, y];\n            }\n            var crz = pathArray.length == 3 && pathArray[0][0] == \"M\" && pathArray[1][0].toUpperCase() == \"R\" && pathArray[2][0].toUpperCase() == \"Z\";\n            for (var r, pa, i = start, ii = pathArray.length; i < ii;
57590 i++) {\n                res.push(r = []);\n                pa = pathArray[i];\n                if (pa[0] != upperCase.call(pa[0])) {\n                    r[0] = upperCase.call(pa[0]);\n                    switch (r[0]) {\n                        case \"A\":\n                            r[1] = pa[1];\n                            r[2] = pa[2];\n                            r[3] = pa[3];\n                            r[4] = pa[4];\n                            r[5] = pa[5];\n                            r[6] = +(pa[6] + x);\n                            r[7] = +(pa[7] + y);\n                            break;\n                        case \"V\":\n                            r[1] = +pa[1] + y;\n                            break;\n                        case \"H\":\n                            r[1] = +pa[1] + x;\n                            break;\n                        case \"R\":\n                            var dots = [x, y][concat](pa.slice(1));\n                            for (var j = 2, jj = dots.length; j < jj; j++) {\n                                dots[j] = +dots[j] + x;\n                                dots[++j] = +dots[j] + y;\n                            }\n                            res.pop();\n                            res = res[concat](catmullRom2bezier(dots, crz));\n                            break;\n                        case \"M\":\n                            mx = +pa[1] + x;\n                            my = +pa[2] + y;\n                        default:\n                            for (j = 1, jj = pa.length; j < jj; j++) {\n                                r[j] = +pa[j] + ((j % 2) ? x : y);\n                            }\n                    }\n                } else if (pa[0] == \"R\") {\n                    dots = [x, y][concat](pa.slice(1));\n                    res.pop();\n                    res = res[concat](catmullRom2bezier(dots, crz));\n                    r = [\"R\"][concat](pa.slice(-2));\n                } else {\n                    for (var k = 0, kk = pa.length; k < kk; k++) {\n                        r[k] = pa[k];\n                    }\n                }\n                switch (r[0]) {\n                    case \"Z\":\n                        x = mx;\n                        y = my;\n                        break;\n                    case \"H\":\n                        x = r[1];\n                        break;\n                    case \"V\":\n                        y = r[1];\n                        break;\n                    case \"M\":\n                        mx = r[r.length - 2];\n                        my = r[r.length - 1];\n                    default:\n                        x = r[r.length - 2];\n                        y = r[r.length - 1];\n                }\n            }\n            res.toString = R._path2string;\n            pth.abs = pathClone(res);\n            return res;\n        },\n        l2c = function (x1, y1, x2, y2) {\n            return [x1, y1, x2, y2, x2, y2];\n        },\n        q2c = function (x1, y1, ax, ay, x2, y2) {\n            var _13 = 1 / 3,\n                _23 = 2 / 3;\n            return [\n                    _13 * x1 + _23 * ax,\n                    _13 * y1 + _23 * ay,\n                    _13 * x2 + _23 * ax,\n                    _13 * y2 + _23 * ay,\n                    x2,\n                    y2\n                ];\n        },\n        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {\n            // for more information of where this math came from visit:\n            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes\n            var _120 = PI * 120 / 180,\n                rad = PI / 180 * (+angle || 0),\n                res = [],\n                xy,\n                rotate = cacher(function (x, y, rad) {\n                    var X = x * math.cos(rad) - y * math.sin(rad),\n                        Y = x * math.sin(rad) + y * math.cos(rad);\n                    return {x: X, y: Y};\n                });\n            if (!recursive) {\n                xy = rotate(x1, y1, -rad);\n                x1 = xy.x;\n                y1 = xy.y;\n                xy = rotate(x2, y2, -rad);\n                x2 = xy.x;\n                y2 = xy.y;\n                var cos = math.cos(PI / 180 * angle),\n                    sin = math.sin(PI / 180 * angle),\n                    x = (x1 - x2) / 2,\n                    y = (y1 - y2) / 2;\n                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);\n                if (h > 1) {\n                    h = math.sqrt(h);\n                    rx = h * rx;\n                    ry = h * ry;\n                }\n                var rx2 = rx * rx,\n                    ry2 = ry * ry,\n                    k = (large_arc_flag == sweep_flag ? -1 : 1) *\n                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),\
57590n                    cx = k * rx * y / ry + (x1 + x2) / 2,\n                    cy = k * -ry * x / rx + (y1 + y2) / 2,\n                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),\n                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));\n\n                f1 = x1 < cx ? PI - f1 : f1;\n                f2 = x2 < cx ? PI - f2 : f2;\n                f1 < 0 && (f1 = PI * 2 + f1);\n                f2 < 0 && (f2 = PI * 2 + f2);\n                if (sweep_flag && f1 > f2) {\n                    f1 = f1 - PI * 2;\n                }\n                if (!sweep_flag && f2 > f1) {\n                    f2 = f2 - PI * 2;\n                }\n            } else {\n                f1 = recursive[0];\n                f2 = recursive[1];\n                cx = recursive[2];\n                cy = recursive[3];\n            }\n            var df = f2 - f1;\n            if (abs(df) > _120) {\n                var f2old = f2,\n                    x2old = x2,\n                    y2old = y2;\n                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);\n                x2 = cx + rx * math.cos(f2);\n                y2 = cy + ry * math.sin(f2);\n                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);\n            }\n            df = f2 - f1;\n            var c1 = math.cos(f1),\n                s1 = math.sin(f1),\n                c2 = math.cos(f2),\n                s2 = math.sin(f2),\n                t = math.tan(df / 4),\n                hx = 4 / 3 * rx * t,\n                hy = 4 / 3 * ry * t,\n                m1 = [x1, y1],\n                m2 = [x1 + hx * s1, y1 - hy * c1],\n                m3 = [x2 + hx * s2, y2 - hy * c2],\n                m4 = [x2, y2];\n            m2[0] = 2 * m1[0] - m2[0];\n            m2[1] = 2 * m1[1] - m2[1];\n            if (recursive) {\n                return [m2, m3, m4][concat](res);\n            } else {\n                res = [m2, m3, m4][concat](res).join()[split](\",\");\n                var newres = [];\n                for (var i = 0, ii = res.length; i < ii; i++) {\n                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;\n                }\n                return newres;\n            }\n        },\n        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n            var t1 = 1 - t;\n            return {\n                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,\n                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y\n            };\n        },\n        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),\n                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),\n                c = p1x - c1x,\n                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,\n                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,\n                y = [p1y, p2y],\n                x = [p1x, p2x],\n                dot;\n            abs(t1) > \"1e12\" && (t1 = .5);\n            abs(t2) > \"1e12\" && (t2 = .5);\n            if (t1 > 0 && t1 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            if (t2 > 0 && t2 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);\n            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);\n            c = p1y - c1y;\n            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;\n            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;\n            abs(t1) > \"1e12\" && (t1 = .5);\n            abs(t2) > \"1e12\" && (t2 = .5);\n            if (t1 > 0 && t1 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            if (t2 > 0 && t2 < 1) {\n                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n                x.push(dot.x);\n                y.push(dot.y);\n            }\n            return {\n                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},\n                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}\n            };\n        }),\n        path2curve = R._path2curve = cacher(function (path, path2) {\n            var pth = !path2 && paths(path);\n            if (!path2 && pth.curve) {\n                return pathClone(pth.curve);\n            }\n            var p = pathToAbsolute(path),\n                p2 = path2 && pathToAbsolute(path2),\n                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n                processPath = function (path, d, pcom) {\n                    var nx, ny, tq = {T:1, Q:1};\n                    if (!path) {\n                        return [\"C\", d.x, d.y, d.x, d.y, d.x, d.y];\n                    }\n                    !(path[0] in tq) && (d.qx = d.qy = null);\n                    switch (path[0]) {\n                        case \"M\":\n                            d.X = path[1];\n                            d.Y = path[2];\n                            break;\n                        case \"A\":\n                            path = [\"C\"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));\n                            break;\n                        case \"S\":\n                            if (pcom == \"C\" || pcom == \"S\") { // In \"S\" case we have to take into account, if the previous command is C/S.\n                                nx = d.x * 2 - d.bx;          // And reflect the previous\n                                ny = d.y * 2 - d.by;          // command's control point relative to the current point.\n                            }\n                            else {                            // or some else or nothing\n                                nx = d.x;\n                                ny = d.y;\n                            }\n                            path = [\"C\", nx, ny][concat](path.slice(1));\n                            break;\n                        case \"T\":\n                            if (pcom == \"Q\" || pcom == \"T\") { // In \"T\" case we have to take into account, if the previous command is Q/T.\n                                d.qx = d.x * 2 - d.qx;        // And make a reflection similar\n                                d.qy = d.y * 2 - d.qy;        // to case \"S\".\n                            }\n                            else {                            // or something else or nothing\n                                d.qx = d.x;\n                                d.qy = d.y;\n                            }\n                            path = [\"C\"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));\n                            break;\n                        case \"Q\":\n                            d.qx = path[1];\n                            d.qy = path[2];\n                            path = [\"C\"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));\n                            break;\n                        case \"L\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, path[1], path[2]));\n                            break;\n                        case \"H\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, path[1], d.y));\n                            break;\n                        case \"V\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, d.x, path[1]));\n                            break;\n                        case \"Z\":\n                            path = [\"C\"][concat](l2c(d.x, d.y, d.X, d.Y));\n                            break;\n                    }\n                    return path;\n                },\n                fixArc = function (pp, i) {\n                    if (pp[i].length > 7) {\n                        pp[i].shift();\n                        var pi = pp[i];\n                        while (pi.length) {\n                            pcoms1[i]=\"A\"; // if created multiple C:s, their original seg is saved\n                            p2 && (pcoms2[i]=\"A\"); // the same as above\n                            pp.splice(i++, 0, [\"C\"][concat](pi.splice(0, 6)));\n                        }\n                        pp.splice(i, 1);\n                        ii = mmax(p.length, p2 && p2.length || 0);\n                    }\n                },\n                fixM = function (path1, path2, a1, a2, i) {\n                    if (path1 && path2 && path1[i][0] == \"M\" && path2[i][0] != \"M\") {\n                        path2.splice(i, 0, [\"M\", a2.x, a2.y]);\n                        a1.bx = 0;\n                        a1.by = 0;\n                        a1.x = path1[i][1];\n                        a1.y = path1[i][2];\n                        ii = mmax(p.length, p2 && p2.length || 0);\n                    }\n                },\n                pcoms1 = [], // path commands of original path p\n                pcoms2 = [], // path commands of original path p2\n                pfirst = \"\", // temporary holder for original path command\n                pcom = \"\"; // holder for previous path command of original path\n            for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii;
57590 i++) {\n                p[i] && (pfirst = p[i][0]); // save current path command\n\n                if (pfirst != \"C\") // C is not saved yet, because it may be result of conversion\n                {\n                    pcoms1[i] = pfirst; // Save current path command\n                    i && ( pcom = pcoms1[i-1]); // Get previous path command pcom\n                }\n                p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath\n\n                if (pcoms1[i] != \"A\" && pfirst == \"C\") pcoms1[i] = \"C\"; // A is the only command\n                // which may produce multiple C:s\n                // so we have to make sure that C is also C in original path\n\n                fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1\n\n                if (p2) { // the same procedures is done to p2\n                    p2[i] && (pfirst = p2[i][0]);\n                    if (pfirst != \"C\")\n                    {\n                        pcoms2[i] = pfirst;\n                        i && (pcom = pcoms2[i-1]);\n                    }\n                    p2[i] = processPath(p2[i], attrs2, pcom);\n\n                    if (pcoms2[i]!=\"A\" && pfirst==\"C\") pcoms2[i]=\"C\";\n\n                    fixArc(p2, i);\n                }\n                fixM(p, p2, attrs, attrs2, i);\n                fixM(p2, p, attrs2, attrs, i);\n                var seg = p[i],\n                    seg2 = p2 && p2[i],\n                    seglen = seg.length,\n                    seg2len = p2 && seg2.length;\n                attrs.x = seg[seglen - 2];\n                attrs.y = seg[seglen - 1];\n                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;\n                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;\n                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);\n                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);\n                attrs2.x = p2 && seg2[seg2len - 2];\n                attrs2.y = p2 && seg2[seg2len - 1];\n            }\n            if (!p2) {\n                pth.curve = pathClone(p);\n            }\n            return p2 ? [p, p2] : p;\n        }, null, pathClone),\n        parseDots = R._parseDots = cacher(function (gradient) {\n            var dots = [];\n            for (var i = 0, ii = gradient.length; i < ii; i++) {\n                var dot = {},\n                    par = gradient[i].match(/^([^:]*):?([\\d\\.]*)/);\n                dot.color = R.getRGB(par[1]);\n                if (dot.color.error) {\n                    return null;\n                }\n                dot.opacity = dot.color.opacity;\n                dot.color = dot.color.hex;\n                par[2] && (dot.offset = par[2] + \"%\");\n                dots.push(dot);\n            }\n            for (i = 1, ii = dots.length - 1; i < ii; i++) {\n                if (!dots[i].offset) {\n                    var start = toFloat(dots[i - 1].offset || 0),\n                        end = 0;\n                    for (var j = i + 1; j < ii; j++) {\n                        if (dots[j].offset) {\n                            end = dots[j].offset;\n                            break;\n                        }\n                    }\n                    if (!end) {\n                        end = 100;\n                        j = ii;\n                    }\n                    end = toFloat(end);\n                    var d = (end - start) / (j - i + 1);\n                    for (; i < j; i++) {\n                        start += d;\n                        dots[i].offset = start + \"%\";\n                    }\n                }\n            }\n            return dots;\n        }),\n        tear = R._tear = function (el, paper) {\n            el == paper.top && (paper.top = el.prev);\n            el == paper.bottom && (paper.bottom = el.next);\n            el.next && (el.next.prev = el.prev);\n            el.prev && (el.prev.next = el.next);\n        },\n        tofront = R._tofront = function (el, paper) {\n            if (paper.top === el) {\n                return;\n            }\n            tear(el, paper);\n            el.next = null;\n            el.prev = paper.top;\n            paper.top.next = el;\n            paper.top = el;\n        },\n        toback = R._toback = function (el, paper) {\n            if (paper.bottom === el) {\n                return;\n            }\n            tear(el, paper);\n            el.next = paper.bottom;\n            el.prev = null;\n            paper.bottom.prev = el;\n            paper.bottom = el;\n        },\n        insertafter = R._insertafter = function (el, el2, paper) {\n            tear(el, paper);\n            el2 == paper.top && (paper.top = el);\n            el2.next && (el2.next.prev = el);\n            el.next = el2.next;\n            el.prev = el2;\n            el2.next = el;\n        },\n        insertbefore = R._insertbefore = function (el, el2, paper) {\n            tear(el, paper);\n            el2 == paper.bottom && (paper.bottom = el);\n            el2.prev && (el2.prev.next = el);\n            el.prev = el2.prev;\n            el2.prev = el;\n            el.next = el2;\n        },\n        /*\\\n         * Raphael.toMatrix\n         [ method ]\n         **\n         * Utility method\n         **\n         * Returns matrix of transformations applied to a given path\n         > Parameters\n         - path (string) path string\n         - transform (string|array) transformation string\n         = (object) @Matr
57590ix\n        \\*/\n        toMatrix = R.toMatrix = function (path, transform) {\n            var bb = pathDimensions(path),\n                el = {\n                    _: {\n                        transform: E\n                    },\n                    getBBox: function () {\n                        return bb;\n                    }\n                };\n            extractTransform(el, transform);\n            return el.matrix;\n        },\n        /*\\\n         * Raphael.transformPath\n         [ method ]\n         **\n         * Utility method\n         **\n         * Returns path transformed by a given transformation\n         > Parameters\n         - path (string) path string\n         - transform (string|array) transformation string\n         = (string) path\n        \\*/\n        transformPath = R.transformPath = function (path, transform) {\n            return mapPath(path, toMatrix(path, transform));\n        },\n        extractTransform = R._extractTransform = function (el, tstr) {\n            if (tstr == null) {\n                return el._.transform;\n            }\n            tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, el._.transform || E);\n            var tdata = R.parseTransformString(tstr),\n                deg = 0,\n                dx = 0,\n                dy = 0,\n                sx = 1,\n                sy = 1,\n                _ = el._,\n                m = new Matrix;\n            _.transform = tdata || [];\n            if (tdata) {\n                for (var i = 0, ii = tdata.length; i < ii; i++) {\n                    var t = tdata[i],\n                        tlen = t.length,\n                        command = Str(t[0]).toLowerCase(),\n                        absolute = t[0] != command,\n                        inver = absolute ? m.invert() : 0,\n                        x1,\n                        y1,\n                        x2,\n                        y2,\n                        bb;\n                    if (command == \"t\" && tlen == 3) {\n                        if (absolute) {\n                            x1 = inver.x(0, 0);\n                            y1 = inver.y(0, 0);\n                            x2 = inver.x(t[1], t[2]);\n                            y2 = inver.y(t[1], t[2]);\n                            m.translate(x2 - x1, y2 - y1);\n                        } else {\n                            m.translate(t[1], t[2]);\n                        }\n                    } else if (command == \"r\") {\n                        if (tlen == 2) {\n                            bb = bb || el.getBBox(1);\n                            m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n                            deg += t[1];\n                        } else if (tlen == 4) {\n                            if (absolute) {\n                                x2 = inver.x(t[2], t[3]);\n                                y2 = inver.y(t[2], t[3]);\n                                m.rotate(t[1], x2, y2);\n                            } else {\n                                m.rotate(t[1], t[2], t[3]);\n                            }\n                            deg += t[1];\n                        }\n                    } else if (command == \"s\") {\n                        if (tlen == 2 || tlen == 3) {\n                            bb = bb || el.getBBox(1);\n                            m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n                            sx *= t[1];\n                            sy *= t[tlen - 1];\n                        } else if (tlen == 5) {\n                            if (absolute) {\n                                x2 = inver.x(t[3], t[4]);\n                                y2 = inver.y(t[3], t[4]);\n                                m.scale(t[1], t[2], x2, y2);\n                            } else {\n                                m.scale(t[1], t[2], t[3], t[4]);\n                            }\n                            sx *= t[1];\n                            sy *= t[2];\n                        }\n                    } else if (command == \"m\" && tlen == 7) {\n                        m.add(t[1], t[2], t[3], t[4], t[5], t[6]);\n                    }\n                    _.dirtyT = 1;\n                    el.matrix = m;\n                }\n            }\n\n            /*\\\n             * Element.matrix\n             [ property (object) ]\n             **\n             * Keeps @Matrix object, which represents element transformation\n            \\*/\n            el.matrix = m;\n\n            _.sx = sx;\n            _.sy = sy;\n            _.deg = deg;\n            _.dx = dx = m.e;\n            _.dy = dy = m.f;\n\n            if (sx == 1 && sy == 1 && !deg && _.bbox) {\n                _.bbox.x += +dx;\n                _.bbox.y += +dy;\n            } else {\n                _.dirtyT = 1;\n            }\n        },\n        getEmpty = function (item) {\n            var l = item[0];\n            switch (l.toLowerCase()) {\n                case \"t\": return [l, 0, 0];\n                case \"m\": return [l, 1, 0, 0, 1, 0, 0];\n                case \"r\": if (item.length == 4) {\n                    return [l, 0, item[2], item[3]];\n                } else {\n                    return [l, 0];\n                }\n                case \"s\": if (item.length == 5) {\n                    return [l, 1, 1, item[3], item[4]];\n                } else if (item.length == 3) {\n                    return [l, 1, 1];\n                } else {\n                    return [l, 1];\n                }\n            }\n        },\n        equaliseTransform = R._equaliseTransform = function (t1, t2) {\n            t2 = Str(t2).replace(/\\.{3}|\\u2026/g, t1);\n            t1 = R.parseTransformString(t1) || [];\n            t2 = R.parseTransformString(t2) || [];\n            var maxlength = mmax(t1.length, t2.length),\n                from = [],\n                to = [],\n                i = 0, j, jj,\n                tt1, tt2;\n            for (; i < maxlength;
57590 i++) {\n                tt1 = t1[i] || getEmpty(t2[i]);\n                tt2 = t2[i] || getEmpty(tt1);\n                if ((tt1[0] != tt2[0]) ||\n                    (tt1[0].toLowerCase() == \"r\" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||\n                    (tt1[0].toLowerCase() == \"s\" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))\n                    ) {\n                    return;\n                }\n                from[i] = [];\n                to[i] = [];\n                for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {\n                    j in tt1 && (from[i][j] = tt1[j]);\n                    j in tt2 && (to[i][j] = tt2[j]);\n                }\n            }\n            return {\n                from: from,\n                to: to\n            };\n        };\n    R._getContainer = function (x, y, w, h) {\n        var container;\n        container = h == null && !R.is(x, \"object\") ? g.doc.getElementById(x) : x;\n        if (container == null) {\n            return;\n        }\n        if (container.tagName) {\n            if (y == null) {\n                return {\n                    container: container,\n                    width: container.style.pixelWidth || container.offsetWidth,\n                    height: container.style.pixelHeight || container.offsetHeight\n                };\n            } else {\n                return {\n                    container: container,\n                    width: y,\n                    height: w\n                };\n            }\n        }\n        return {\n            container: 1,\n            x: x,\n            y: y,\n            width: w,\n            height: h\n        };\n    };\n    /*\\\n     * Raphael.pathToRelative\n     [ method ]\n     **\n     * Utility method\n     **\n     * Converts path to relative form\n     > Parameters\n     - pathString (string|array) path string or array of segments\n     = (array) array of segments.\n    \\*/\n    R.pathToRelative = pathToRelative;\n    R._engine = {};\n    /*\\\n     * Raphael.path2curve\n     [ method ]\n     **\n     * Utility method\n     **\n     * Converts path to a new path where all segments are cubic bezier curves.\n     > Parameters\n     - pathString (string|array) path string or array of segments\n     = (array) array of segments.\n    \\*/\n    R.path2curve = path2curve;\n    /*\\\n     * Raphael.matrix\n     [ method ]\n     **\n     * Utility method\n     **\n     * Returns matrix based on given parameters.\n     > Parameters\n     - a (number)\n     - b (number)\n     - c (number)\n     - d (number)\n     - e (number)\n     - f (number)\n     = (object) @Matrix\n    \\*/\n    R.matrix = function (a, b, c, d, e, f) {\n        return new Matrix(a, b, c, d, e, f);\n    };\n    function Matrix(a, b, c, d, e, f) {\n        if (a != null) {\n            this.a = +a;\n            this.b = +b;\n            this.c = +c;\n            this.d = +d;\n            this.e = +e;\n            this.f = +f;\n        } else {\n            this.a = 1;\n            this.b = 0;\n            this.c = 0;\n            this.d = 1;\n            this.e = 0;\n            this.f = 0;\n        }\n    }\n    (function (matrixproto) {\n        /*\\\n         * Matrix.add\n         [ method ]\n         **\n         * Adds given matrix to existing one.\n         > Parameters\n         - a (number)\n         - b (number)\n         - c (number)\n         - d (number)\n         - e (number)\n         - f (number)\n         or\n         - matrix (object) @Matrix\n        \\*/\n        matrixproto.add = function (a, b, c, d, e, f) {\n            var out = [[], [], []],\n                m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],\n                matrix = [[a, c, e], [b, d, f], [0, 0, 1]],\n                x, y, z, res;\n\n            if (a && a instanceof Matrix) {\n                matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];\n            }\n\n            for (x = 0; x < 3; x++) {\n                for (y = 0; y < 3; y++) {\n                    res = 0;\n                    for (z = 0; z < 3; z++) {\n                        res += m[x][z] * matrix[z][y];\n                    }\n                    out[x][y] = res;\n                }\n            }\n            this.a = out[0][0];\n            this.b = out[1][0];\n            this.c = out[0][1];\n            this.d = out[1][1];\n            this.e = out[0][2];\n            this.f = out[1][2];\n        };\n        /*\\\n         * Matrix.invert\n         [ method ]\n         **\n         * Returns inverted version of the matrix\n         = (object) @Matr
57590ix\n        \\*/\n        matrixproto.invert = function () {\n            var me = this,\n                x = me.a * me.d - me.b * me.c;\n            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);\n        };\n        /*\\\n         * Matrix.clone\n         [ method ]\n         **\n         * Returns copy of the matrix\n         = (object) @Matrix\n        \\*/\n        matrixproto.clone = function () {\n            return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);\n        };\n        /*\\\n         * Matrix.translate\n         [ method ]\n         **\n         * Translate the matrix\n         > Parameters\n         - x (number)\n         - y (number)\n        \\*/\n        matrixproto.translate = function (x, y) {\n            this.add(1, 0, 0, 1, x, y);\n        };\n        /*\\\n         * Matrix.scale\n         [ method ]\n         **\n         * Scales the matrix\n         > Parameters\n         - x (number)\n         - y (number) #optional\n         - cx (number) #optional\n         - cy (number) #optional\n        \\*/\n        matrixproto.scale = function (x, y, cx, cy) {\n            y == null && (y = x);\n            (cx || cy) && this.add(1, 0, 0, 1, cx, cy);\n            this.add(x, 0, 0, y, 0, 0);\n            (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);\n        };\n        /*\\\n         * Matrix.rotate\n         [ method ]\n         **\n         * Rotates the matrix\n         > Parameters\n         - a (number)\n         - x (number)\n         - y (number)\n        \\*/\n        matrixproto.rotate = function (a, x, y) {\n            a = R.rad(a);\n            x = x || 0;\n            y = y || 0;\n            var cos = +math.cos(a).toFixed(9),\n                sin = +math.sin(a).toFixed(9);\n            this.add(cos, sin, -sin, cos, x, y);\n            this.add(1, 0, 0, 1, -x, -y);\n        };\n        /*\\\n         * Matrix.x\n         [ method ]\n         **\n         * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y\n         > Parameters\n         - x (number)\n         - y (number)\n         = (number) x\n        \\*/\n        matrixproto.x = function (x, y) {\n            return x * this.a + y * this.c + this.e;\n        };\n        /*\\\n         * Matrix.y\n         [ method ]\n         **\n         * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x\n         > Parameters\n         - x (number)\n         - y (number)\n         = (number) y\n        \\*/\n        matrixproto.y = function (x, y) {\n            return x * this.b + y * this.d + this.f;\n        };\n        matrixproto.get = function (i) {\n            return +this[Str.fromCharCode(97 + i)].toFixed(4);\n        };\n        matrixproto.toString = function () {\n            return R.svg ?\n                \"matrix(\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + \")\" :\n                [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();\n        };\n        matrixproto.toFilter = function () {\n            return \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + this.get(0) +\n                \", M12=\" + this.get(2) + \", M21=\" + this.get(1) + \", M22=\" + this.get(3) +\n                \", Dx=\" + this.get(4) + \", Dy=\" + this.get(5) + \", sizingmethod='auto expand')\";\n        };\n        matrixproto.offset = function () {\n            return [this.e.toFixed(4), this.f.toFixed(4)];\n        };\n        function norm(a) {\n            return a[0] * a[0] + a[1] * a[1];\n        }\n        function normalize(a) {\n            var mag = math.sqrt(norm(a));\n            a[0] && (a[0] /= mag);\n            a[1] && (a[1] /= mag);\n        }\n        /*\\\n         * Matrix.split\n         [ method ]\n         **\n         * Splits matrix into primitive transformations\n         = (object) in format:\n         o dx (number) translation by x\n         o dy (number) translation by y\n         o scalex (number) scale by x\n         o scaley (number) scale by y\n         o shear (number) shear\n         o rotate (number) rotation in deg\n         o isSimple (boolean) could it be represented via simple transformations\n        \\*/\n        matrixproto.split = function () {\n            var out = {};\n            // translation\n            out.dx = this.e;\n            out.dy = this.f;\n\n            // scale and shear\n            var row = [[this.a, this.c], [this.b, this.d]];\n            out.scalex = math.sqrt(norm(row[0]));\n            normalize(row[0]);\n\n            out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];\n            row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];\n\n            out.scaley = math.sqrt(norm(row[1]));\n            normalize(row[1]);\n            out.shear /= out.scaley;\n\n            // rotation\n            var sin = -row[0][1],\n                cos = row[1][1];\n            if (cos < 0) {\n                out.rotate = R.deg(math.acos(cos));\n                if (sin < 0) {\n                    out.rotate = 360 - out.rotate;\n                }\n            } else {\n                out.rotate = R.deg(math.asin(sin));\n            }\n\n            out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);\n            out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;\n            out.noRotation = !+out.shear.toFixed(9) && !out.rotate;\n            return out;\n        };\n        /*\\\n         * Matrix.toTransformString\n         [ method ]\n         **\n         * Return transform string that represents given matrix\n         = (string) transform string\n        \\*/\n        matrixproto.toTransformString = function (shorter) {\n            var s = shorter || this[split]();\n            if (s.isSimple) {\n                s.scalex = +s.scalex.toFixed(4);\n                s.scaley = +s.scaley.toFixed(4);\n                s.rotate = +s.rotate.toFixed(4);\n                return  (s.dx || s.dy ? \"t\" + [s.dx, s.dy] : E) +\n                        (s.scalex != 1 || s.scaley != 1 ? \"s\" + [s.scalex, s.scaley, 0, 0] : E) +\n                        (s.rotate ? \"r\" + [s.rotate, 0, 0] : E);\n            } else {\n                return \"m\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];\n            }\n        };\n    })(Matrix.prototype);\n\n    var preventDefault = function () {\n        this.returnValue = false;\n    },\n    preventTouch = function () {\n        return this.originalEvent.preventDefault();\n    },\n    stopPropagation = function () {\n        this.cancelBubble = true;\n    },\n    stopTouch = function () {\n        return this.originalEvent.stopPropagation();\n    },\n    getEventPosition = function (e) {\n        var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n\n        return {\n            x: e.clientX + scrollX,\n            y: e.clientY + scrollY\n        };\n    },\n    addEvent = (function () {\n        if (g.doc.addEventListener) {\n            return function (obj, type, fn, element) {\n                var f = function (e) {\n                    var pos = getEventPosition(e);
57590\n                    return fn.call(element, e, pos.x, pos.y);\n                };\n                obj.addEventListener(type, f, false);\n\n                if (supportsTouch && touchMap[type]) {\n                    var _f = function (e) {\n                        var pos = getEventPosition(e),\n                            olde = e;\n\n                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {\n                            if (e.targetTouches[i].target == obj) {\n                                e = e.targetTouches[i];\n                                e.originalEvent = olde;\n                                e.preventDefault = preventTouch;\n                                e.stopPropagation = stopTouch;\n                                break;\n                            }\n                        }\n\n                        return fn.call(element, e, pos.x, pos.y);\n                    };\n                    obj.addEventListener(touchMap[type], _f, false);\n                }\n\n                return function () {\n                    obj.removeEventListener(type, f, false);\n\n                    if (supportsTouch && touchMap[type])\n                        obj.removeEventListener(touchMap[type], _f, false);\n\n                    return true;\n                };\n            };\n        } else if (g.doc.attachEvent) {\n            return function (obj, type, fn, element) {\n                var f = function (e) {\n                    e = e || g.win.event;\n                    var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n                        scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n                        x = e.clientX + scrollX,\n                        y = e.clientY + scrollY;\n                    e.preventDefault = e.preventDefault || preventDefault;\n                    e.stopPropagation = e.stopPropagation || stopPropagation;\n                    return fn.call(element, e, x, y);\n                };\n                obj.attachEvent(\"on\" + type, f);\n                var detacher = function () {\n                    obj.detachEvent(\"on\" + type, f);\n                    return true;\n                };\n                return detacher;\n            };\n        }\n    })(),\n    drag = [],\n    dragMove = function (e) {\n        var x = e.clientX,\n            y = e.clientY,\n            scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n            dragi,\n            j = drag.length;\n        while (j--) {\n            dragi = drag[j];\n            if (supportsTouch && e.touches) {\n                var i = e.touches.length,\n                    touch;\n                while (i--) {\n                    touch = e.touches[i];\n                    if (touch.identifier == dragi.el._drag.id) {\n                        x = touch.clientX;\n                        y = touch.clientY;\n                        (e.originalEvent ? e.originalEvent : e).preventDefault();\n                        break;\n                    }\n                }\n            } else {\n                e.preventDefault();\n            }\n            var node = dragi.el.node,\n                o,\n                next = node.nextSibling,\n                parent = node.parentNode,\n                display = node.style.display;\n            g.win.opera && parent.removeChild(node);\n            node.style.display = \"none\";\n            o = dragi.el.paper.getElementByPoint(x, y);\n            node.style.display = display;\n            g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));\n            o && eve(\"raphael.drag.over.\" + dragi.el.id, dragi.el, o);\n            x += scrollX;\n            y += scrollY;\n            eve(\"raphael.drag.move.\" + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);\n        }\n    },\n    dragUp = function (e) {\n        R.unmousemove(dragMove).unmouseup(dragUp);\n        var i = drag.length,\n            dragi;\n        while (i--) {\n            dragi = drag[i];\n            dragi.el._drag = {};\n            eve(\"raphael.drag.end.\" + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);\n        }\n        drag = [];\n    },\n    /*\\\n     * Raphael.el\n     [ property (object) ]\n     **\n     * You can add your own method to elements. This is useful when you want to hack default functionality or\n     * want to wrap some common transformation or attributes in one method. In difference to canvas methods,\n     * you can redefine element method at any time. Expending element methods wouldn’t affect set.\n     > Usage\n     | Raphael.el.red = function () {\n     |     this.attr({fill: \"#f00\"});\n     | };\n     | // then use it\n     | paper.circle(100, 100, 20).red();\n    \\*/\n    elproto = R.el = {};\n    /*\\\n     * Element.click\n     [ method ]\n     **\n     * Adds event handler for click for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.unclick\n     [ method ]\n     **\n     * Removes event handler for click for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.dblclick\n     [ method ]\n     **\n     * Adds event handler for double click for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.undblclick\n     [ method ]\n     **\n     * Removes event handler for double click for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.mousedown\n     [ method ]\n     **\n     * Adds event handler for mousedown for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.unmousedown\n     [ method ]\n     **\n     * Removes event handler for mousedown for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.mousemove\n     [ method ]\n     **\n     * Adds event handler for mousemove for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.unmousemove\n     [ method ]\n     **\n     * Removes event handler for mousemove for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.mouseout\n     [ method ]\n     **\n     * Adds event handler for mouseout for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.unmouseout\n     [ method ]\n     **\n     * Removes event handler for mouseout for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.mouseover\n     [ method ]\n     **\n     * Adds event handler for mouseover for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.unmouseover\n     [ method ]\n     **\n     * Removes event handler for mouseover for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.mouseup\n     [ method ]\n     **\n     * Adds event handler for mouseup for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.unmouseup\n     [ method ]\n     **\n     * Removes event handler for mouseup for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.touchstart\n     [ method ]\n     **\n     * Adds event handler for touchstart for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.untouchstart\n     [ method ]\n     **\n     * Removes event handler for touchstart for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.touchmove\n     [ method ]\n     **\n     * Adds event handler for touchmove for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.untouchmove\n     [ method ]\n     **\n     * Removes event handler for touchmove for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.touchend\n     [ method ]\n     **\n     * Adds event handler for touchend for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.untouchend\n     [ method ]\n     **\n     * Removes event handler for touchend for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n\n    /*\\\n     * Element.touchcancel\n     [ method ]\n     **\n     * Adds event handler for touchcancel for the element.\n     > Parameters\n     - handler (function) handler for the event\n     = (object) @Element\n    \\*/\n    /*\\\n     * Element.untouchcancel\n     [ method ]\n     **\n     * Removes event handler for touchcancel for the element.\n     > Parameters\n     - handler (function) #optional handler for the event\n     = (object) @Element\n    \\*/\n    for (var i = events.length; i--;) {\n        (function (eventName) {\n            R[eventName] = elproto[eventName] = function (fn, scope) {\n                if (R.is(fn, \"function\")) {\n                    this.events = this.events || [];\n                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});\n                }\n                return this;\n            };\n            R[\"un\" + eventName] = elproto[\"un\" + eventName] = function (fn) {\n                var events = this.events || [],\n                    l = events.length;\n                while (l--){\n                    if (events[l].name == eventName && (R.is(fn, \"undefined\") || events[l].f == fn)) {\n                        events[l].unbind();\n                        events.splice(l, 1);\n                        !events.length && delete this.events;\n                    }\n                }\n                return this;\n            };\n        })(events[i]);\n    }\n\n    /*\\\n     * Element.data\n     [ method ]\n     **\n     * Adds or retrieves given value associated with given key.\n     **\n     * See also @Element.removeData\n     > Parameters\n     - key (string) key to store data\n     - value (any) #optional value to store\n     = (object) @Element\n     * or, if value is not specified:\n     = (any) value\n     * or, if key and value are not specified:\n     = (object) Key/value pairs for all the data associated with the element.\n     >
57590 Usage\n     | for (var i = 0, i < 5, i++) {\n     |     paper.circle(10 + 15 * i, 10, 10)\n     |          .attr({fill: \"#000\"})\n     |          .data(\"i\", i)\n     |          .click(function () {\n     |             alert(this.data(\"i\"));\n     |          });\n     | }\n    \\*/\n    elproto.data = function (key, value) {\n        var data = eldata[this.id] = eldata[this.id] || {};\n        if (arguments.length == 0) {\n            return data;\n        }\n        if (arguments.length == 1) {\n            if (R.is(key, \"object\")) {\n                for (var i in key) if (key[has](i)) {\n                    this.data(i, key[i]);\n                }\n                return this;\n            }\n            eve(\"raphael.data.get.\" + this.id, this, data[key], key);\n            return data[key];\n        }\n        data[key] = value;\n        eve(\"raphael.data.set.\" + this.id, this, value, key);\n        return this;\n    };\n    /*\\\n     * Element.removeData\n     [ method ]\n     **\n     * Removes value associated with an element by given key.\n     * If key is not provided, removes all the data of the element.\n     > Parameters\n     - key (string) #optional key\n     = (object) @Element\n    \\*/\n    elproto.removeData = function (key) {\n        if (key == null) {\n            delete eldata[this.id];\n        } else {\n            eldata[this.id] && delete eldata[this.id][key];\n        }\n        return this;\n    };\n     /*\\\n     * Element.getData\n     [ method ]\n     **\n     * Retrieves the element data\n     = (object) data\n    \\*/\n    elproto.getData = function () {\n        return clone(eldata[this.id] || {});\n    };\n    /*\\\n     * Element.hover\n     [ method ]\n     **\n     * Adds event handlers for hover for the element.\n     > Parameters\n     - f_in (function) handler for hover in\n     - f_out (function) handler for hover out\n     - icontext (object) #optional context for hover in handler\n     - ocontext (object) #optional context for hover out handler\n     = (object) @Element\n    \\*/\n    elproto.hover = function (f_in, f_out, scope_in, scope_out) {\n        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);\n    };\n    /*\\\n     * Element.unhover\n     [ method ]\n     **\n     * Removes event handlers for hover for the element.\n     > Parameters\n     - f_in (function) handler for hover in\n     - f_out (function) handler for hover out\n     = (object) @Element\n    \\*/\n    elproto.unhover = function (f_in, f_out) {\n        return this.unmouseover(f_in).unmouseout(f_out);\n    };\n    var draggable = [];\n    /*\\\n     * Element.drag\n     [ method ]\n     **\n     * Adds event handlers for drag of the element.\n     > Parameters\n     - onmove (function) handler for moving\n     - onstart (function) handler for drag start\n     - onend (function) handler for drag end\n     - mcontext (object) #optional context for moving handler\n     - scontext (object) #optional context for drag start handler\n     - econtext (object) #optional context for drag end handler\n     * Additionally following `drag` events will be triggered: `drag.start.<id>` on start,\n     * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element\n     * `drag.over.<id>` will be fired as well.\n     *\n     * Start event and start handler will be called in specified context or in context of the element with following parameters:\n     o x (number) x position of the mouse\n     o y (number) y position of the mouse\n     o event (object) DOM event object\n     * Move event and move handler will be called in specified context or in context of the element with following parameters:\n     o dx (number) shift by x from the start point\n     o dy (number) shift by y from the start point\n     o x (number) x position of the mouse\n     o y (number) y position of the mouse\n     o event (object) DOM event object\n     * End event and end handler will be called in specified context or in context of the element with following parameters:\n     o event (object) DOM event object\n     = (object) @Element\n    \\*/\n    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {\n        function start(e) {\n            (e.originalEvent || e).preventDefault();
57590\n            var x = e.clientX,\n                y = e.clientY,\n                scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n                scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n            this._drag.id = e.identifier;\n            if (supportsTouch && e.touches) {\n                var i = e.touches.length, touch;\n                while (i--) {\n                    touch = e.touches[i];\n                    this._drag.id = touch.identifier;\n                    if (touch.identifier == this._drag.id) {\n                        x = touch.clientX;\n                        y = touch.clientY;\n                        break;\n                    }\n                }\n            }\n            this._drag.x = x + scrollX;\n            this._drag.y = y + scrollY;\n            !drag.length && R.mousemove(dragMove).mouseup(dragUp);\n            drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});\n            onstart && eve.on(\"raphael.drag.start.\" + this.id, onstart);\n            onmove && eve.on(\"raphael.drag.move.\" + this.id, onmove);\n            onend && eve.on(\"raphael.drag.end.\" + this.id, onend);\n            eve(\"raphael.drag.start.\" + this.id, start_scope || move_scope || this, this._drag.x, this._drag.y, e);\n        }\n        this._drag = {};\n        draggable.push({el: this, start: start});\n        this.mousedown(start);\n        return this;\n    };\n    /*\\\n     * Element.onDragOver\n     [ method ]\n     **\n     * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id).\n     > Parameters\n     - f (function) handler for event, first argument would be the element you are dragging over\n    \\*/\n    elproto.onDragOver = function (f) {\n        f ? eve.on(\"raphael.drag.over.\" + this.id, f) : eve.unbind(\"raphael.drag.over.\" + this.id);\n    };\n    /*\\\n     * Element.undrag\n     [ method ]\n     **\n     * Removes all drag event handlers from given element.\n    \\*/\n    elproto.undrag = function () {\n        var i = draggable.length;\n        while (i--) if (draggable[i].el == this) {\n            this.unmousedown(draggable[i].start);\n            draggable.splice(i, 1);\n            eve.unbind(\"raphael.drag.*.\" + this.id);\n        }\n        !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);\n        drag = [];\n    };\n    /*\\\n     * Paper.circle\n     [ method ]\n     **\n     * Draws a circle.\n     **\n     > Parameters\n     **\n     - x (number) x coordinate of the centre\n     - y (number) y coordinate of the centre\n     - r (number) radius\n     = (object) Raphaël element object with type “circle”\n     **\n     > Usage\n     | var c = paper.circle(50, 50, 40);\n    \\*/\n    paperproto.circle = function (x, y, r) {\n        var out = R._engine.circle(this, x || 0, y || 0, r || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Paper.rect\n     [ method ]\n     *\n     * Draws a rectangle.\n     **\n     > Parameters\n     **\n     - x (number) x coordinate of the top left corner\n     - y (number) y coordinate of the top left corner\n     - width (number) width\n     - height (number) height\n     - r (number) #optional radius for rounded corners, default is 0\n     = (object) Raphaël element object with type “rect”\n     **\n     > Usage\n     | // regular rectangle\n     | var c = paper.rect(10, 10, 50, 50);\n     | // rectangle with rounded corners\n     | var c = paper.rect(40, 40, 50, 50, 10);\n    \\*/\n    paperproto.rect = function (x, y, w, h, r) {\n        var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Paper.ellipse\n     [ method ]\n     **\n     * Draws an ellipse.\n     **\n     > Parameters\n     **\n     - x (number) x coordinate of the centre\n     - y (number) y coordinate of the centre\n     - rx (number) horizontal radius\n     - ry (number) vertical radius\n     = (object) Raphaël element object with type “ellipse”\n     **\n     > Usage\n     | var c = paper.ellipse(50, 50, 40, 20);\n    \\*/\n    paperproto.ellipse = function (x, y, rx, ry) {\n        var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Paper.path\n     [ method ]\n     **\n     * Creates a path element by given path data string.\n     > Parameters\n     - pathString (string) #optional path string in SVG format.\n     * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:\n     | \"M10,20L30,40\"\n     * Here we can see two commands: “M”, with arguments `(10, 20)` and “L” with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative.\n     *\n     # <p>Here is short list of commands available, for more details see <a href=\"http://www.w3.org/TR/SVG/paths.html#PathData\" title=\"Details of a path's data attribute's format are described 
57590in the SVG specification.\">SVG path string format</a>.</p>\n     # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>\n     # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>\n     # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>\n     # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>\n     # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>\n     # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>\n     # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>\n     # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>\n     # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>\n     # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>\n     # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>\n     # <tr><td>R</td><td><a href=\"http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline\">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>\n     * * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier.\n     * Note: there is a special case when path consist of just three commands: “M10,10R…z”. In this case path will smoothly connects to its beginning.\n     > Usage\n     | var c = paper.path(\"M10 10L90 90\");\n     | // draw a diagonal line:\n     | // move to 10,10, line to 90,90\n     * For example of path strings, check out these icons: http://raphaeljs.com/icons/\n    \\*/\n    paperproto.path = function (pathString) {\n        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);\n        var out = R._engine.path(R.format[apply](R, arguments), this);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Paper.image\n     [ method ]\n     **\n     * Embeds an image into the surface.\n     **\n     > Parameters\n     **\n     - src (string) URI of the source image\n     - x (number) x coordinate position\n     - y (number) y coordinate position\n     - width (number) width of the image\n     - height (number) height of the image\n     = (object) Raphaël element object with type “image”\n     **\n     > Usage\n     | var c = paper.image(\"apple.png\", 10, 10, 80, 80);\n    \\*/\n    paperproto.image = function (src, x, y, w, h) {\n        var out = R._engine.image(this, src || \"about:blank\", x || 0, y || 0, w || 0, h || 0);\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Paper.text\n     [ method ]\n     **\n     * Draws a text string. If you need line breaks, put “\\n” in the string.\n     **\n     > Parameters\n     **\n     - x (number) x coordinate position\n     - y (number) y coordinate position\n     - text (string) The text string to draw\n     = (object) Raphaël element object with type “text”\n     **\n     > Usage\n     | var t = paper.text(50, 50, \"Raphaël\\nkicks\\nbutt!\");\n    \\*/\n    paperproto.text = function (x, y, text) {\n        var out = R._engine.text(this, x || 0, y || 0, Str(text));\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Paper.set\n     [ method ]\n     **\n     * Creates array-like object to keep and operate several elements at once.\n     * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements.\n     * Sets act as pseudo elements — all methods available to an element can be used on a set.\n     = (object) array-like object that represents set of elements\n     **\n     > Usage\n     | var st = paper.set();\n     | st.push(\n     |     paper.circle(10, 10, 5),\n     |     paper.circle(30, 10, 5)\n     | );\n     | st.attr({fill: \"red\"}); // changes the fill of both circles\n    \\*/\n    paperproto.set = function (itemsArray) {\n        !R.is(itemsArray, \"array\") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));\n        var out = new Set(itemsArray);\n        this.__set__ && this.__set__.push(out);\n        out[\"paper\"] = this;\n        out[\"type\"] = \"set\";\n        return out;\n    };\n    /*\\\n     * Paper.setStart\n     [ method ]\n     **\n     * Creates @Paper.set. All elements that will be created after calling this method and before calling\n     * @Paper.setFinish will be added to the set.\n     **\n     > Usage\n     | paper.setStart();\n     | paper.circle(10, 10, 5),\n     | paper.circle(30, 10, 5)\n     | var st = paper.setFinish();\n     | st.attr({fill: \"red\"}); // changes the fill of both circles\n    \\*/\n    paperproto.setStart = function (set) {\n        this.__set__ = set || this.set();\n    };\n    /*\\\n     * Paper.setFinish\n     [ method ]\n     **\n     * See @Paper.setStart. This method finishes catching and returns resulting set.\n     **\n     = (object) set\n    \\*/\n    paperproto.setFinish = function (set) {\n        var out = this.__set__;\n        delete this.__set__;\n        return out;\n    };\n    /*\\\n     * Paper.getSize\n     [ method ]\n     **\n     * Obtains current paper actual size.\n     **\n     = (object)\n     \\*/\n    paperproto.getSize = function () {\n        var container = this.canvas.parentNode;\n        return {\n            width: container.offsetWidth,\n            height: container.offsetHeight\n                };\n        };\n    /*\\\n     * Paper.setSize\n     [ method ]\n     **\n     * If you need to change dimensions of the canvas call this method\n     **\n     > Parameters\n     **\n     - width (number) new width of the canvas\n     - he
57590ight (number) new height of the canvas\n    \\*/\n    paperproto.setSize = function (width, height) {\n        return R._engine.setSize.call(this, width, height);\n    };\n    /*\\\n     * Paper.setViewBox\n     [ method ]\n     **\n     * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by\n     * specifying new boundaries.\n     **\n     > Parameters\n     **\n     - x (number) new x position, default is `0`\n     - y (number) new y position, default is `0`\n     - w (number) new width of the canvas\n     - h (number) new height of the canvas\n     - fit (boolean) `true` if you want graphics to fit into new boundary box\n    \\*/\n    paperproto.setViewBox = function (x, y, w, h, fit) {\n        return R._engine.setViewBox.call(this, x, y, w, h, fit);\n    };\n    /*\\\n     * Paper.top\n     [ property ]\n     **\n     * Points to the topmost element on the paper\n    \\*/\n    /*\\\n     * Paper.bottom\n     [ property ]\n     **\n     * Points to the bottom element on the paper\n    \\*/\n    paperproto.top = paperproto.bottom = null;\n    /*\\\n     * Paper.raphael\n     [ property ]\n     **\n     * Points to the @Raphael object/function\n    \\*/\n    paperproto.raphael = R;\n    var getOffset = function (elem) {\n        var box = elem.getBoundingClientRect(),\n            doc = elem.ownerDocument,\n            body = doc.body,\n            docElem = doc.documentElement,\n            clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,\n            top  = box.top  + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,\n            left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;\n        return {\n            y: top,\n            x: left\n        };\n    };\n    /*\\\n     * Paper.getElementByPoint\n     [ method ]\n     **\n     * Returns you topmost element under given point.\n     **\n     = (object) Raphaël element object\n     > Parameters\n     **\n     - x (number) x coordinate from the top left corner of the window\n     - y (number) y coordinate from the top left corner of the window\n     > Usage\n     | paper.getElementByPoint(mouseX, mouseY).attr({stroke: \"#f00\"});\n    \\*/\n    paperproto.getElementByPoint = function (x, y) {\n        var paper = this,\n            svg = paper.canvas,\n            target = g.doc.elementFromPoint(x, y);\n        if (g.win.opera && target.tagName == \"svg\") {\n            var so = getOffset(svg),\n                sr = svg.createSVGRect();\n            sr.x = x - so.x;\n            sr.y = y - so.y;\n            sr.width = sr.height = 1;\n            var hits = svg.getIntersectionList(sr, null);\n            if (hits.length) {\n                target = hits[hits.length - 1];\n            }\n        }\n        if (!target) {\n            return null;\n        }\n        while (target.parentNode && target != svg.parentNode && !target.raphael) {\n            target = target.parentNode;\n        }\n        target == paper.canvas.parentNode && (target = svg);\n        target = target && target.raphael ? paper.getById(target.raphaelid) : null;\n        return target;\n    };\n\n    /*\\\n     * Paper.getElementsByBBox\n     [ method ]\n     **\n     * Returns set of elements that have an intersecting bounding box\n     **\n     > Parameters\n     **\n     - bbox (object) bbox to check with\n     = (object) @Set\n     \\*/\n    paperproto.getElementsByBBox = function (bbox) {\n        var set = this.set();\n        this.forEach(function (el) {\n            if (R.isBBoxIntersect(el.getBBox(), bbox)) {\n                set.push(el);\n            }\n        });\n        return set;\n    };\n\n    /*\\\n     * Paper.getById\n     [ method ]\n     **\n     * Returns you element by its internal ID.\n     **\n     > Parameters\n     **\n     - id (number) id\n     = (object) Raphaël element object\n    \\*/\n    paperproto.getById = function (id) {\n        var bot = this.bottom;\n        while (bot) {\n            if (bot.id == id) {\n                return bot;\n            }\n            bot = bot.next;\n        }\n        return null;\n    };\n    /*\\\n     * Paper.forEach\n     [ method ]\n     **\n     * Executes given function for each element on the paper\n     *\n     * If callback function returns `false` it will stop loop running.\n     **\n     > Parameters\n     **\n     - callback (function) function to run\n     - thisArg (object) context object for the callback\n     = (object) Paper object\n     > Usage\n     | paper.forEach(function (el) {\n     |     el.attr({ stroke: \"blue\" });\n     | });\n    \\*/\n    paperproto.forEach = function (callback, thisArg) {\n        var bot = this.bottom;\n        while (bot) {\n            if (callback.call(thisArg, bot) === false) {\n                return this;\n            }\n            bot = bot.next;\n        }\n        return this;\n    };\n    /*\\\n     * Paper.getElementsByPoint\n     [ method ]\n     **\n     * Returns set of elements that have common point inside\n     **\n     > Parameters\n     **\n     - x (number) x coordinate of the point\n     - y (number) y coordinate of the point\n     = (object) @Set\n    \\*/\n    paperproto.getElementsByPoint = function (x, y) {\n        var set = this.set();\n        this.forEach(function (el) {\n            if (el.isPointInside(x, y)) {\n                set.push(el);\n            }\n        });\n        return set;\n    };\n    function x_y() {\n        return this.x + S + this.y;\n    }\n    function x_y_w_h() {\n        return this.x + S + this.y + S + this.width + \" \\xd7 \" + this.height;\n    }\n    /*\\\n     * Element.isPointInside\n     [ method ]\n     **\n     * Determine if given point is inside this element’s shape\n     **\n     > Parameters\n     **\n     - x (number) x coordinate of the point\n     - y (number) y coordinate of the point\n     = (boolean) `true` if point inside the shape\n    \\*/\n    elproto.isPointInside = function (x, y) {\n        var rp = this.realPath = getPath[this.type](this);\n        if (this.attr('transform') && this.attr('transform').length) {\n            rp = R.transformPath(rp, this.attr('transform'));\n        }\n        return R.isPointInsidePath(rp, x, y);\n    };\n    /*\\\n     * Element.getBBox\n     [ method ]\n     **\n     * Return bounding box for a given element\n     **\n     > Parameters\n     **\n     - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.\n     = (object) Bounding box object:\n     o {\n     o     x: (number) top left corner x\n     o     y: (number) top left corner y\n     o     x2: (number) bottom right corner x\n     o     y2: (number) bottom right corner y\n     o     width: (number) width\n     o     height: (number) height\n     o }\n    \\*/\n    elproto.getBBox = function (isWithoutTransform) {\n        if (this.removed) {\
57590n            return {};\n        }\n        var _ = this._;\n        if (isWithoutTransform) {\n            if (_.dirty || !_.bboxwt) {\n                this.realPath = getPath[this.type](this);\n                _.bboxwt = pathDimensions(this.realPath);\n                _.bboxwt.toString = x_y_w_h;\n                _.dirty = 0;\n            }\n            return _.bboxwt;\n        }\n        if (_.dirty || _.dirtyT || !_.bbox) {\n            if (_.dirty || !this.realPath) {\n                _.bboxwt = 0;\n                this.realPath = getPath[this.type](this);\n            }\n            _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));\n            _.bbox.toString = x_y_w_h;\n            _.dirty = _.dirtyT = 0;\n        }\n        return _.bbox;\n    };\n    /*\\\n     * Element.clone\n     [ method ]\n     **\n     = (object) clone of a given element\n     **\n    \\*/\n    elproto.clone = function () {\n        if (this.removed) {\n            return null;\n        }\n        var out = this.paper[this.type]().attr(this.attr());\n        this.__set__ && this.__set__.push(out);\n        return out;\n    };\n    /*\\\n     * Element.glow\n     [ method ]\n     **\n     * Return set of elements that create glow-like effect around given element. See @Paper.set.\n     *\n     * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.\n     **\n     > Parameters\n     **\n     - glow (object) #optional parameters object with all properties optional:\n     o {\n     o     width (number) size of the glow, default is `10`\n     o     fill (boolean) will it be filled, default is `false`\n     o     opacity (number) opacity, default is `0.5`\n     o     offsetx (number) horizontal offset, default is `0`\n     o     offsety (number) vertical offset, default is `0`\n     o     color (string) glow colour, default is `black`\n     o }\n     = (object) @Paper.set of elements that represents glow\n    \\*/\n    elproto.glow = function (glow) {\n        if (this.type == \"text\") {\n            return null;\n        }\n        glow = glow || {};\n        var s = {\n            width: (glow.width || 10) + (+this.attr(\"stroke-width\") || 1),\n            fill: glow.fill || false,\n            opacity: glow.opacity == null ? .5 : glow.opacity,\n            offsetx: glow.offsetx || 0,\n            offsety: glow.offsety || 0,\n            color: glow.color || \"#000\"\n        },\n            c = s.width / 2,\n            r = this.paper,\n            out = r.set(),\n            path = this.realPath || getPath[this.type](this);\n        path = this.matrix ? mapPath(path, this.matrix) : path;\n        for (var i = 1; i < c + 1; i++) {\n            out.push(r.path(path).attr({\n                stroke: s.color,\n                fill: s.fill ? s.color : \"none\",\n                \"stroke-linejoin\": \"round\",\n                \"stroke-linecap\": \"round\",\n                \"stroke-width\": +(s.width / c * i).toFixed(3),\n                opacity: +(s.opacity / c).toFixed(3)\n            }));\n        }\n        return out.insertBefore(this).translate(s.offsetx, s.offsety);\n    };\n    var curveslengths = {},\n    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {\n        if (length == null) {\n            return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);\n        } else {\n            return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));\n        }\n    },\n    getLengthFactory = function (istotal, subpath) {\n        return function (path, length, onlystart) {\n            path = path2curve(path);\n            var x, y, p, l, sp = \"\", subpaths = {}, point,\n                len = 0;\n            for (var i = 0, ii = path.length; i < ii; i++) {\n                p = path[i];\n                if (p[0] == \"M\") {\n                    x = +p[1];\n                    y = +p[2];\n                } else {\n                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n                    if (len + l > length) {\n                        if (subpath && !subpaths.start) {\n                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n                            sp += [\"C\" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];\n                            if (onlystart) {return sp;}\n                            subpaths.start = sp;\n                            sp = [\"M\" + point.x, point.y + \"C\" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();\n                            len += l;\n                            x = +p[5];\n                            y = +p[6];\n                            continue;\n                        }\n                        if (!istotal && !subpath) {\n                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n                            return {x: point.x, y: point.y, alph
57590a: point.alpha};\n                        }\n                    }\n                    len += l;\n                    x = +p[5];\n                    y = +p[6];\n                }\n                sp += p.shift() + p;\n            }\n            subpaths.end = sp;\n            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);\n            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});\n            return point;\n        };\n    };\n    var getTotalLength = getLengthFactory(1),\n        getPointAtLength = getLengthFactory(),\n        getSubpathsAtLength = getLengthFactory(0, 1);\n    /*\\\n     * Raphael.getTotalLength\n     [ method ]\n     **\n     * Returns length of the given path in pixels.\n     **\n     > Parameters\n     **\n     - path (string) SVG path string.\n     **\n     = (number) length.\n    \\*/\n    R.getTotalLength = getTotalLength;\n    /*\\\n     * Raphael.getPointAtLength\n     [ method ]\n     **\n     * Return coordinates of the point located at the given length on the given path.\n     **\n     > Parameters\n     **\n     - path (string) SVG path string\n     - length (number)\n     **\n     = (object) representation of the point:\n     o {\n     o     x: (number) x coordinate\n     o     y: (number) y coordinate\n     o     alpha: (number) angle of derivative\n     o }\n    \\*/\n    R.getPointAtLength = getPointAtLength;\n    /*\\\n     * Raphael.getSubpath\n     [ method ]\n     **\n     * Return subpath of a given path from given length to given length.\n     **\n     > Parameters\n     **\n     - path (string) SVG path string\n     - from (number) position of the start of the segment\n     - to (number) position of the end of the segment\n     **\n     = (string) pathstring for the segment\n    \\*/\n    R.getSubpath = function (path, from, to) {\n        if (this.getTotalLength(path) - to < 1e-6) {\n            return getSubpathsAtLength(path, from).end;\n        }\n        var a = getSubpathsAtLength(path, to, 1);\n        return from ? getSubpathsAtLength(a, from).end : a;\n    };\n    /*\\\n     * Element.getTotalLength\n     [ method ]\n     **\n     * Returns length of the path in pixels. Only works for element of “path” type.\n     = (number) length.\n    \\*/\n    elproto.getTotalLength = function () {\n        var path = this.getPath();\n        if (!path) {\n            return;\n        }\n\n        if (this.node.getTotalLength) {\n            return this.node.getTotalLength();\n        }\n\n        return getTotalLength(path);\n    };\n    /*\\\n     * Element.getPointAtLength\n     [ method ]\n     **\n     * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type.\n     **\n     > Parameters\n     **\n     - length (number)\n     **\n     = (object) representation of the point:\n     o {\n     o     x: (number) x coordinate\n     o     y: (number) y coordinate\n     o     alpha: (number) angle of derivative\n     o }\n    \\*/\n    elproto.getPointAtLength = function (length) {\n        var path = this.getPath();\n        if (!path) {\n            return;\n        }\n\n        return getPointAtLength(path, length);\n    };\n    /*\\\n     * Element.getPath\n     [ method ]\n     **\n     * Returns path of the element. Only works for elements of “path” type and simple elements like circle.\n     = (object) path\n     **\n    \\*/\n    elproto.getPath = function () {\n        var path,\n            getPath = R._getPath[this.type];\n\n        if (this.type == \"text\" || this.type == \"set\") {\n            return;\n        }\n\n        if (getPath) {\n            path = getPath(this);\n        }\n\n        return path;\n    };\n    /*\\\n     * Element.getSubpath\n     [ method ]\n     **\n     * Return subpath of a given element from given length to given length. Only works for element of “path” type.\n     **\n     > Parameters\n     **\n     - from (number) position of the start of the segment\n     - to (number) position of the end of the segment\n     **\n     = (string) pathstring for the segment\n    \\*/\n    elproto.getSubpath = function (from, to) {\n        var path = this.getPath();\n        if (!path) {\n            return;\n        }\n\n        return R.getSubpath(path, from, to);\n    };\n    /*\\\n     * Raphael.easing_formulas\n     [ property ]\n     **\n     * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:\n     # <ul>\n     #     <li>“linear”</li>\n     #     <li>“&lt;” or “easeIn” or “ease-in”</li>\n     #     <li>“>” or “easeOut” or “ease-out”</li>\n     #     <li>“&lt;>” or “easeInOut” or “ease-in-out”</li>\n     #     <li>“backIn” or “back-in”</li>\n     #     <li>
57590“backOut” or “back-out”</li>\n     #     <li>“elastic”</li>\n     #     <li>“bounce”</li>\n     # </ul>\n     # <p>See also <a href=\"http://raphaeljs.com/easing.html\">Easing demo</a>.</p>\n    \\*/\n    var ef = R.easing_formulas = {\n        linear: function (n) {\n            return n;\n        },\n        \"<\": function (n) {\n            return pow(n, 1.7);\n        },\n        \">\": function (n) {\n            return pow(n, .48);\n        },\n        \"<>\": function (n) {\n            var q = .48 - n / 1.04,\n                Q = math.sqrt(.1734 + q * q),\n                x = Q - q,\n                X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),\n                y = -Q - q,\n                Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),\n                t = X + Y + .5;\n            return (1 - t) * 3 * t * t + t * t * t;\n        },\n        backIn: function (n) {\n            var s = 1.70158;\n            return n * n * ((s + 1) * n - s);\n        },\n        backOut: function (n) {\n            n = n - 1;\n            var s = 1.70158;\n            return n * n * ((s + 1) * n + s) + 1;\n        },\n        elastic: function (n) {\n            if (n == !!n) {\n                return n;\n            }\n            return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;\n        },\n        bounce: function (n) {\n            var s = 7.5625,\n                p = 2.75,\n                l;\n            if (n < (1 / p)) {\n                l = s * n * n;\n            } else {\n                if (n < (2 / p)) {\n                    n -= (1.5 / p);\n                    l = s * n * n + .75;\n                } else {\n                    if (n < (2.5 / p)) {\n                        n -= (2.25 / p);\n                        l = s * n * n + .9375;\n                    } else {\n                        n -= (2.625 / p);\n                        l = s * n * n + .984375;\n                    }\n                }\n            }\n            return l;\n        }\n    };\n    ef.easeIn = ef[\"ease-in\"] = ef[\"<\"];\n    ef.easeOut = ef[\"ease-out\"] = ef[\">\"];\n    ef.easeInOut = ef[\"ease-in-out\"] = ef[\"<>\"];\n    ef[\"back-in\"] = ef.backIn;\n    ef[\"back-out\"] = ef.backOut;\n\n    var animationElements = [],\n        requestAnimFrame = window.requestAnimationFrame       ||\n                           window.webkitRequestAnimationFrame ||\n                           window.mozRequestAnimationFrame    ||\n                           window.oRequestAnimationFrame      ||\n                           window.msRequestAnimationFrame     ||\n                           function (callback) {\n                               setTimeout(callback, 16);\n                           },\n        animation = function () {\n            var Now = +new Date,\n                l = 0;\n            for (; l < animationElements.length; l++) {\n                var e = animationElements[l];\n                if (e.el.removed || e.paused) {\n                    continue;\n                }\n                var time = Now - e.start,\n                    ms = e.ms,\n                    easing = e.easing,\n                    from = e.from,\n                    diff = e.diff,\n                    to = e.to,\n                    t = e.t,\n                    that = e.el,\n                    set = {},\n                    now,\n                    init = {},\n                    key;\n                if (e.initstatus) {\n                    time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;\n                    e.status = e.initstatus;\n                    delete e.initstatus;\n                    e.stop && animationElements.splice(l--, 1);\n                } else {\n                    e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;\n                }\n                if (time < 0) {\n                    continue;\n                }\n                if (time < ms) {\n                    var pos = easing(time / ms);\n                    for (var attr in from) if (from[has](attr)) {\n                        switch (availableAnimAttrs[attr]) {\n                            case nu:\n                                now = +from[attr] + pos * ms * diff[attr];\n                                break;\n                            case \"colour\":\n                                now = \"rgb(\" + [\n                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),\n                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),\n                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))\n                                ].join(\",\") + \")\";\n                                break;\n                            case \"path\":\n                                now = [];\n                                for (var i = 0, ii = from[attr].length; i < ii;
57590 i++) {\n                                    now[i] = [from[attr][i][0]];\n                                    for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];\n                                    }\n                                    now[i] = now[i].join(S);\n                                }\n                                now = now.join(S);\n                                break;\n                            case \"transform\":\n                                if (diff[attr].real) {\n                                    now = [];\n                                    for (i = 0, ii = from[attr].length; i < ii; i++) {\n                                        now[i] = [from[attr][i][0]];\n                                        for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                            now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];\n                                        }\n                                    }\n                                } else {\n                                    var get = function (i) {\n                                        return +from[attr][i] + pos * ms * diff[attr][i];\n                                    };\n                                    // now = [[\"r\", get(2), 0, 0], [\"t\", get(3), get(4)], [\"s\", get(0), get(1), 0, 0]];\n                                    now = [[\"m\", get(0), get(1), get(2), get(3), get(4), get(5)]];\n                                }\n                                break;\n                            case \"csv\":\n                                if (attr == \"clip-rect\") {\n                                    now = [];\n                                    i = 4;\n                                    while (i--) {\n                                        now[i] = +from[attr][i] + pos * ms * diff[attr][i];\n                                    }\n                                }\n                                break;\n                            default:\n                                var from2 = [][concat](from[attr]);\n                                now = [];\n                                i = that.paper.customAttributes[attr].length;\n                                while (i--) {\n                                    now[i] = +from2[i] + pos * ms * diff[attr][i];\n                                }\n                                break;\n                        }\n                        set[attr] = now;\n                    }\n                    that.attr(set);\n                    (function (id, that, anim) {\n                        setTimeout(function () {\n                            eve(\"raphael.anim.frame.\" + id, that, anim);\n                        });\n                    })(that.id, that, e.anim);\n                } else {\n                    (function(f, el, a) {\n                        setTimeout(function() {\n                            eve(\"raphael.anim.frame.\" + el.id, el, a);\n                            eve(\"raphael.anim.finish.\" + el.id, el, a);\n                            R.is(f, \"function\") && f.call(el);\n                        });\n                    })(e.callback, that, e.anim);\n                    that.attr(to);\n                    animationElements.splice(l--, 1);\n                    if (e.repeat > 1 && !e.next) {\n                        for (key in to) if (to[has](key)) {\n                            init[key] = e.totalOrigin[key];\n                        }\n                        e.el.attr(init);\n                        runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);\n                    }\n                    if (e.next && !e.stop) {\n                        runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);\n                    }\n                }\n            }\n            animationElements.length && requestAnimFrame(animation);\n        },\n        upto255 = function (color) {\n            return color > 255 ? 255 : color < 0 ? 0 : color;\n        };\n    /*\\\n     * Element.animateWith\n     [ method ]\n     **\n     * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element.\n     **\n     > Parameters\n     **\n     - el (object) element to sync with\n     - anim (object) animation to sync with\n     - params (object) #optional final attributes for the element, see also @Element.attr\n     - ms (number) #optional number of milliseconds for animation to run\n     - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`\n     - callback (function) #optional callback function. Will be called at the end of animation.\n     * or\n     - element (object) element to sync with\n     - anim (object) animation to sync with\n     - animation (object) #optional animation object, see @Raphael.animation\n     **\n     = (object) original element\n    \\*/\n    elproto.animateWith = function (el, anim, params, ms, easing, callback) {\n        var element = this;
57590\n        if (element.removed) {\n            callback && callback.call(element);\n            return element;\n        }\n        var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),\n            x, y;\n        runAnimation(a, element, a.percents[0], null, element.attr());\n        for (var i = 0, ii = animationElements.length; i < ii; i++) {\n            if (animationElements[i].anim == anim && animationElements[i].el == el) {\n                animationElements[ii - 1].start = animationElements[i].start;\n                break;\n            }\n        }\n        return element;\n        //\n        //\n        // var a = params ? R.animation(params, ms, easing, callback) : anim,\n        //     status = element.status(anim);\n        // return this.animate(a).status(a, status * anim.ms / a.ms);\n    };\n    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {\n        var cx = 3 * p1x,\n            bx = 3 * (p2x - p1x) - cx,\n            ax = 1 - cx - bx,\n            cy = 3 * p1y,\n            by = 3 * (p2y - p1y) - cy,\n            ay = 1 - cy - by;\n        function sampleCurveX(t) {\n            return ((ax * t + bx) * t + cx) * t;\n        }\n        function solve(x, epsilon) {\n            var t = solveCurveX(x, epsilon);\n            return ((ay * t + by) * t + cy) * t;\n        }\n        function solveCurveX(x, epsilon) {\n            var t0, t1, t2, x2, d2, i;\n            for(t2 = x, i = 0; i < 8; i++) {\n                x2 = sampleCurveX(t2) - x;\n                if (abs(x2) < epsilon) {\n                    return t2;\n                }\n                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;\n                if (abs(d2) < 1e-6) {\n                    break;\n                }\n                t2 = t2 - x2 / d2;\n            }\n            t0 = 0;\n            t1 = 1;\n            t2 = x;\n            if (t2 < t0) {\n                return t0;\n            }\n            if (t2 > t1) {\n                return t1;\n            }\n            while (t0 < t1) {\n                x2 = sampleCurveX(t2);\n                if (abs(x2 - x) < epsilon) {\n                    return t2;\n                }\n                if (x > x2) {\n                    t0 = t2;\n                } else {\n                    t1 = t2;\n                }\n                t2 = (t1 - t0) / 2 + t0;\n            }\n            return t2;\n        }\n        return solve(t, 1 / (200 * duration));\n    }\n    elproto.onAnimation = function (f) {\n        f ? eve.on(\"raphael.anim.frame.\" + this.id, f) : eve.unbind(\"raphael.anim.frame.\" + this.id);\n        return this;\n    };\n    function Animation(anim, ms) {\n        var percents = [],\n            newAnim = {};\n        this.ms = ms;\n        this.times = 1;\n        if (anim) {\n            for (var attr in anim) if (anim[has](attr)) {\n                newAnim[toFloat(attr)] = anim[attr];\n                percents.push(toFloat(attr));\n            }\n            percents.sort(sortByNumber);\n        }\n        this.anim = newAnim;\n        this.top = percents[percents.length - 1];\n        this.percents = percents;\n    }\n    /*\\\n     * Animation.delay\n     [ method ]\n     **\n     * Creates a copy of existing animation object with given delay.\n     **\n     > Parameters\n     **\n     - delay (number) number of ms to pass between animation start and actual animation\n     **\n     = (object) new altered Animation object\n     | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);\n     | circle1.animate(anim); // run the given animation immediately\n     | circle2.animate(anim.delay(500)); // run the given animation after 500 ms\n    \\*/\n    Animation.prototype.delay = function (delay) {\n        var a = new Animation(this.anim, this.ms);\n        a.times = this.times;\n        a.del = +delay || 0;\n        return a;\n    };\n    /*\\\n     * Animation.repeat\n     [ method ]\n     **\n     * Creates a copy of existing animation object with given repetition.\n     **\n     > Parameters\n     **\n     - repeat (number) number iterations of animation. For infinite animation pass `Infinity`\n     **\n     = (object) new altered Animation object\n    \\*/\n    Animation.prototype.repeat = function (times) {\n        var a = new Animation(this.anim, this.ms);\n        a.del = this.del;\n        a.times = math.floor(mmax(times, 0)) || 1;\n        return a;\n    };\n    function runAnimation(anim, element, percent, status, totalOrigin, times) {\n        percent = toFloat(percent);\n        var params,\n            isInAnim,\n            isInAnimSet,\n            percents = [],\n            next,\n            prev,\n            timestamp,\n            ms = anim.ms,\n            from = {},\n            to = {},\n            diff = {};\n        if (status) {\n            for (i = 0, ii = animationElements.length; i < ii;
57590 i++) {\n                var e = animationElements[i];\n                if (e.el.id == element.id && e.anim == anim) {\n                    if (e.percent != percent) {\n                        animationElements.splice(i, 1);\n                        isInAnimSet = 1;\n                    } else {\n                        isInAnim = e;\n                    }\n                    element.attr(e.totalOrigin);\n                    break;\n                }\n            }\n        } else {\n            status = +to; // NaN\n        }\n        for (var i = 0, ii = anim.percents.length; i < ii; i++) {\n            if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {\n                percent = anim.percents[i];\n                prev = anim.percents[i - 1] || 0;\n                ms = ms / anim.top * (percent - prev);\n                next = anim.percents[i + 1];\n                params = anim.anim[percent];\n                break;\n            } else if (status) {\n                element.attr(anim.anim[anim.percents[i]]);\n            }\n        }\n        if (!params) {\n            return;\n        }\n        if (!isInAnim) {\n            for (var attr in params) if (params[has](attr)) {\n                if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {\n                    from[attr] = element.attr(attr);\n                    (from[attr] == null) && (from[attr] = availableAttrs[attr]);\n                    to[attr] = params[attr];\n                    switch (availableAnimAttrs[attr]) {\n                        case nu:\n                            diff[attr] = (to[attr] - from[attr]) / ms;\n                            break;\n                        case \"colour\":\n                            from[attr] = R.getRGB(from[attr]);\n                            var toColour = R.getRGB(to[attr]);\n                            diff[attr] = {\n                                r: (toColour.r - from[attr].r) / ms,\n                                g: (toColour.g - from[attr].g) / ms,\n                                b: (toColour.b - from[attr].b) / ms\n                            };\n                            break;\n                        case \"path\":\n                            var pathes = path2curve(from[attr], to[attr]),\n                                toPath = pathes[1];\n                            from[attr] = pathes[0];\n                            diff[attr] = [];\n                            for (i = 0, ii = from[attr].length; i < ii; i++) {\n                                diff[attr][i] = [0];\n                                for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                    diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;\n                                }\n                            }\n                            break;\n                        case \"transform\":\n                            var _ = element._,\n                                eq = equaliseTransform(_[attr], to[attr]);\n                            if (eq) {\n                                from[attr] = eq.from;\n                                to[attr] = eq.to;\n                                diff[attr] = [];\n                                diff[attr].real = true;\n                                for (i = 0, ii = from[attr].length; i < ii; i++) {\n                                    diff[attr][i] = [from[attr][i][0]];\n                                    for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n                                        diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;\n                                    }\n                                }\n                            } else {\n                                var m = (element.matrix || new Matrix),\n                                    to2 = {\n                                        _: {transform: _.transform},\n                                        getBBox: function () {\n                                            return element.getBBox(1);\n                                        }\n                                    };\n                                from[attr] = [\n                                    m.a,\n                                    m.b,\n                                    m.c,\n                                    m.d,\n                                    m.e,\n                                    m.f\n                                ];\n                                extractTransform(to2, to[attr]);\n                                to[attr] = to2._.transform;\n                                diff[attr] = [\n                                    (to2.matrix.a - m.a) / ms,\n                                    (to2.matrix.b - m.b) / ms,\n                                    (to2.matrix.c - m.c) / ms,\n                                    (to2.matrix.d - m.d) / ms,\n                                    (to2.matrix.e - m.e) / ms,\n                                    (to2.matrix.f - m.f) / ms\n                                ];\n                                // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];\n                                // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};\n                                // extractTransform(to2, to[attr]);\n                                // diff[attr] = [\n                                //     (to2._.sx - _.sx) / ms,\n                                //     (to2._.sy - _.sy) / ms,\n                                //     (to2._.deg - _.deg) / ms,\n                                //     (to2._.dx - _.dx) / ms,\n                                //     (to2._.dy - _.dy) / ms\n                                // ];\n                            }\n                            break;\n                        case \"csv\":\n                            var values = Str(params[attr])[split](separator),\n                                from2 = Str(from[attr])[split](separator);\n                            if (attr == \"clip-rect\") {\n                                from[attr] = from2;\n                                diff[attr] = [];\n                                i = from2.length;\n                                while (i--) {\n                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;\n                                }\n                            }\n                            to[attr] = values;\n                            break;\n                        default:\n                            values = [][concat](params[attr]);\n                            from2 = [][concat](from[attr]);\n                            diff[attr] = [];\n                            i = element.paper.customAttributes[attr].length;\n                            while (i--) {\n                                diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;\n                            }\n                            break;\n                    }\n                }\n            }\n            var easing = params.easing,\n                easyeasy = R.easing_formulas[easing];\n            if (!easyeasy) {\n                easyeasy = Str(easing).match(bezierrg);\n                if (easyeasy && easyeasy.length == 5) {\n                    var curve = easyeasy;\n                    easyeasy = function (t) {\n                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);\n                    };\n                } else {\n                    easyeasy = pipe;\n                }\n            }\n            timestamp = params.start || anim.start || +new Date;\n            e = {\n                anim: anim,\n                percent: percent,\n                timestamp: timestamp,\n                start: timestamp + (anim.del || 0),\
57590n                status: 0,\n                initstatus: status || 0,\n                stop: false,\n                ms: ms,\n                easing: easyeasy,\n                from: from,\n                diff: diff,\n                to: to,\n                el: element,\n                callback: params.callback,\n                prev: prev,\n                next: next,\n                repeat: times || anim.times,\n                origin: element.attr(),\n                totalOrigin: totalOrigin\n            };\n            animationElements.push(e);\n            if (status && !isInAnim && !isInAnimSet) {\n                e.stop = true;\n                e.start = new Date - ms * status;\n                if (animationElements.length == 1) {\n                    return animation();\n                }\n            }\n            if (isInAnimSet) {\n                e.start = new Date - e.ms * status;\n            }\n            animationElements.length == 1 && requestAnimFrame(animation);\n        } else {\n            isInAnim.initstatus = status;\n            isInAnim.start = new Date - isInAnim.ms * status;\n        }\n        eve(\"raphael.anim.start.\" + element.id, element, anim);\n    }\n    /*\\\n     * Raphael.animation\n     [ method ]\n     **\n     * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods.\n     * See also @Animation.delay and @Animation.repeat methods.\n     **\n     > Parameters\n     **\n     - params (object) final attributes for the element, see also @Element.attr\n     - ms (number) number of milliseconds for animation to run\n     - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`\n     - callback (function) #optional callback function. Will be called at the end of animation.\n     **\n     = (object) @Animation\n    \\*/\n    R.animation = function (params, ms, easing, callback) {\n        if (params instanceof Animation) {\n            return params;\n        }\n        if (R.is(easing, \"function\") || !easing) {\n            callback = callback || easing || null;\n            easing = null;\n        }\n        params = Object(params);\n        ms = +ms || 0;\n        var p = {},\n            json,\n            attr;\n        for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat
57590(attr) + \"%\" != attr) {\n            json = true;\n            p[attr] = params[attr];\n        }\n        if (!json) {\n            // if percent-like syntax is used and end-of-all animation callback used\n            if(callback){\n                // find the last one\n                var lastKey = 0;\n                for(var i in params){\n                    var percent = toInt(i);\n                    if(params[has](i) && percent > lastKey){\n                        lastKey = percent;\n                    }\n                }\n                lastKey += '%';\n                // if already defined callback in the last keyframe, skip\n                !params[lastKey].callback && (params[lastKey].callback = callback);\n            }\n          return new Animation(params, ms);\n        } else {\n            easing && (p.easing = easing);\n            callback && (p.callback = callback);\n            return new Animation({100: p}, ms);\n        }\n    };\n    /*\\\n     * Element.animate\n     [ method ]\n     **\n     * Creates and starts animation for given element.\n     **\n     > Parameters\n     **\n     - params (object) final attributes for the element, see also @Element.attr\n     - ms (number) number of milliseconds for animation to run\n     - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`\n     - callback (function) #optional callback function. Will be called at the end of animation.\n     * or\n     - animation (object) animation object, see @Raphael.animation\n     **\n     = (object) original element\n    \\*/\n    elproto.animate = function (params, ms, easing, callback) {\n        var element = this;
57590\n        if (element.removed) {\n            callback && callback.call(element);\n            return element;\n        }\n        var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);\n        runAnimation(anim, element, anim.percents[0], null, element.attr());\n        return element;\n    };\n    /*\\\n     * Element.setTime\n     [ method ]\n     **\n     * Sets the status of animation of the element in milliseconds. Similar to @Element.status method.\n     **\n     > Parameters\n     **\n     - anim (object) animation object\n     - value (number) number of milliseconds from the beginning of the animation\n     **\n     = (object) original element if `value` is specified\n     * Note, that during animation following events are triggered:\n     *\n     * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`.\n    \\*/\n    elproto.setTime = function (anim, value) {\n        if (anim && value != null) {\n            this.status(anim, mmin(value, anim.ms) / anim.ms);\n        }\n        return this;\n    };\n    /*\\\n     * Element.status\n     [ method ]\n     **\n     * Gets or sets the status of animation of the element.\n     **\n     > Parameters\n     **\n     - anim (object) #optional animation object\n     - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position.\n     **\n     = (number) status\n     * or\n     = (array) status if `anim` is not specified. Array of objects in format:\n     o {\n     o     anim: (object) animation object\n     o     status: (number) status\n     o }\n     * or\n     = (object) original element if `value` is specified\n    \\*/\n    elproto.status = function (anim, value) {\n        var out = [],\n            i = 0,\n            len,\n            e;\n        if (value != null) {\n            runAnimation(anim, this, -1, mmin(value, 1));\n            return this;\n        } else {\n            len = animationElements.length;\n            for (; i < len; i++) {\n                e = animationElements[i];\n                if (e.el.id == this.id && (!anim || e.anim == anim)) {\n                    if (anim) {\n                        return e.status;\n                    }\n                    out.push({\n                        anim: e.anim,\n                        status: e.status\n                    });\n                }\n            }\n            if (anim) {\n                return 0;\n            }\n            return out;\n        }\n    };\n    /*\\\n     * Element.pause\n     [ method ]\n     **\n     * Stops animation of the element with ability to resume it later on.\n     **\n     > Parameters\n     **\n     - anim (object) #optional animation object\n     **\n     = (object) original element\n    \\*/\n    elproto.pause = function (anim) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n            if (eve(\"raphael.anim.pause.\" + this.id, this, animationElements[i].anim) !== false) {\n                animationElements[i].paused = true;\n            }\n        }\n        return this;\n    };\n    /*\\\n     * Element.resume\n     [ method ]\n     **\n     * Resumes animation if it was paused with @Element.pause method.\n     **\n     > Parameters\n     **\n     - anim (object) #optional animation object\n     **\n     = (object) original element\n    \\*/\n    elproto.resume = function (anim) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n            var e = animationElements[i];\n            if (eve(\"raphael.anim.resume.\" + this.id, this, e.anim) !== false) {\n                delete e.paused;\n                this.status(e.anim, e.status);\n            }\n        }\n        return this;\n    };\n    /*\\\n     * Element.stop\n     [ method ]\n     **\n     * Stops animation of the element.\n     **\n     > Parameters\n     **\n     - anim (object) #optional animation object\n     **\n     = (object) original element\n    \\*/\n    elproto.stop = function (anim) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n            if (eve(\"raphael.anim.stop.\" + this.id, this, animationElements[i].anim) !== false) {\n                animationElements.splice(i--, 1);\n            }\n        }\n        return this;\n    };\n    function stopAnimation(paper) {\n        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {\n            animationElements.splice(i--, 1);\n        }\n    }\n    eve.on(\"raphael.remove\", stopAnimation);\n    eve.on(\"raphael.clear\", stopAnimation);\n    elproto.toString = function () {\n        return \"Rapha\\xebl\\u2019s object\";\n    };\n\n    // Set\n    var Set = function (items) {\n        this.items = [];\n        this.length = 0;\n        this.type = \"set\";\n        if (items) {\n            for (var i = 0, ii = items.length; i < ii;
57590 i++) {\n                if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {\n                    this[this.items.length] = this.items[this.items.length] = items[i];\n                    this.length++;\n                }\n            }\n        }\n    },\n    setproto = Set.prototype;\n    /*\\\n     * Set.push\n     [ method ]\n     **\n     * Adds each argument to the current set.\n     = (object) original element\n    \\*/\n    setproto.push = function () {\n        var item,\n            len;\n        for (var i = 0, ii = arguments.length; i < ii; i++) {\n            item = arguments[i];\n            if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {\n                len = this.items.length;\n                this[len] = this.items[len] = item;\n                this.length++;\n            }\n        }\n        return this;\n    };\n    /*\\\n     * Set.pop\n     [ method ]\n     **\n     * Removes last element and returns it.\n     = (object) element\n    \\*/\n    setproto.pop = function () {\n        this.length && delete this[this.length--];\n        return this.items.pop();\n    };\n    /*\\\n     * Set.forEach\n     [ method ]\n     **\n     * Executes given function for each element in the set.\n     *\n     * If function returns `false` it will stop loop running.\n     **\n     > Parameters\n     **\n     - callback (function) function to run\n     - thisArg (object) context object for the callback\n     = (object) Set object\n    \\*/\n    setproto.forEach = function (callback, thisArg) {\n        for (var i = 0, ii = this.items.length; i < ii; i++) {\n            if (callback.call(thisArg, this.items[i], i) === false) {\n                return this;\n            }\n        }\n        return this;\n    };\n    for (var method in elproto) if (elproto[has](method)) {\n        setproto[method] = (function (methodname) {\n            return function () {\n                var arg = arguments;\n                return this.forEach(function (el) {\n                    el[methodname][apply](el, arg);\n                });\n            };\n        })(method);\n    }\n    setproto.attr = function (name, value) {\n        if (name && R.is(name, array) && R.is(name[0], \"object\")) {\n            for (var j = 0, jj = name.length; j < jj; j++) {\n                this.items[j].attr(name[j]);\n            }\n        } else {\n            for (var i = 0, ii = this.items.length; i < ii; i++) {\n                this.items[i].attr(name, value);\n            }\n        }\n        return this;\n    };\n    /*\\\n     * Set.clear\n     [ method ]\n     **\n     * Removes all elements from the set\n    \\*/\n    setproto.clear = function () {\n        while (this.length) {\n            this.pop();\n        }\n    };\n    /*\\\n     * Set.splice\n     [ method ]\n     **\n     * Removes given element from the set\n     **\n     > Parameters\n     **\n     - index (number) position of the deletion\n     - count (number) number of element to remove\n     - insertion… (object) #optional elements to insert\n     = (object) set elements that were deleted\n    \\*/\n    setproto.splice = function (index, count, insertion) {\n        index = index < 0 ? mmax(this.length + index, 0) : index;\n        count = mmax(0, mmin(this.length - index, count));\n        var tail = [],\n            todel = [],\n            args = [],\n            i;\n        for (i = 2; i < arguments.length; i++) {\n            args.push(arguments[i]);\n        }\n        for (i = 0; i < count; i++) {\n            todel.push(this[index + i]);\n        }\n        for (; i < this.length - index; i++) {\n            tail.push(this[index + i]);\n        }\n        var arglen = args.length;\n        for (i = 0; i < arglen + tail.length; i++) {\n            this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];\n        }\n        i = this.items.length = this.length -= count - arglen;\n        while (this[i]) {\n            delete this[i++];\n        }\n        return new Set(todel);\n    };\n    /*\\\n     * Set.exclude\n     [ method ]\n     **\n     * Removes given element from the set\n     **\n     > Parameters\n     **\n     - element (object) element to remove\n     = (boolean) `true` if object was found & removed from the set\n    \\*/\n    setproto.exclude = function (el) {\n        for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {\n            this.splice(i, 1);\n            return true;\n        }\n    };\n    setproto.animate = function (params, ms, easing, callback) {\n        (R.is(easing, \"function\") || !easing) && (callback = easing || null);\n        var len = this.items.length,\n            i = len,\n            item,\n            set = this,\n            collector;\n        if (!len) {\n            return this;\n        }\n        callback && (collector = function () {\n            !--len && callback.call(set);\n        });\n        easing = R.is(easing, string) ? easing : collector;\n        var anim = R.animation(params, ms, easing, collector);\n        item = this.items[--i].animate(anim);\n        while (i--) {\n            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);\n            (this.items[i] && !this.items[i].removed) || len--;\n        }\n        return this;\n    };\n    setproto.insertAfter = function (el) {\n        var i = this.items.length;\n        while (i--) {\n            this.items[i].insertAfter(el);\n        }\n        return this;\n    };\n    setproto.getBBox = function () {\n        var x = [],\n            y = [],\n            x2 = [],\n            y2 = [];\n        for (var i = this.items.length; i--;
57590) if (!this.items[i].removed) {\n            var box = this.items[i].getBBox();\n            x.push(box.x);\n            y.push(box.y);\n            x2.push(box.x + box.width);\n            y2.push(box.y + box.height);\n        }\n        x = mmin[apply](0, x);\n        y = mmin[apply](0, y);\n        x2 = mmax[apply](0, x2);\n        y2 = mmax[apply](0, y2);\n        return {\n            x: x,\n            y: y,\n            x2: x2,\n            y2: y2,\n            width: x2 - x,\n            height: y2 - y\n        };\n    };\n    setproto.clone = function (s) {\n        s = this.paper.set();\n        for (var i = 0, ii = this.items.length; i < ii; i++) {\n            s.push(this.items[i].clone());\n        }\n        return s;\n    };\n    setproto.toString = function () {\n        return \"Rapha\\xebl\\u2018s set\";\n    };\n\n    setproto.glow = function(glowConfig) {\n        var ret = this.paper.set();\n        this.forEach(function(shape, index){\n            var g = shape.glow(glowConfig);\n            if(g != null){\n                g.forEach(function(shape2, index2){\n                    ret.push(shape2);\n                });\n            }\n        });\n        return ret;\n    };\n\n\n    /*\\\n     * Set.isPointInside\n     [ method ]\n     **\n     * Determine if given point is inside this set’s elements\n     **\n     > Parameters\n     **\n     - x (number) x coordinate of the point\n     - y (number) y coordinate of the point\n     = (boolean) `true` if point is inside any of the set's elements\n     \\*/\n    setproto.isPointInside = function (x, y) {\n        var isPointInside = false;\n        this.forEach(function (el) {\n            if (el.isPointInside(x, y)) {\n                isPointInside = true;\n                return false; // stop loop\n            }\n        });\n        return isPointInside;\n    };\n\n    /*\\\n     * Raphael.registerFont\n     [ method ]\n     **\n     * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufón’s font file.\n     * Returns original parameter, so it could be used with chaining.\n     # <a href=\"http://wiki.github.com/sorccu/cufon/about\">More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file.</a>\n     **\n     > Parameters\n     **\n     - font (object) the font to register\n     = (object) the font you passed in\n     > Usage\n     | Cufon.registerFont(Raphael.registerFont({…}));\n    \\*/\n    R.registerFont = function (font) {\n        if (!font.face) {\n            return font;\n        }\n        this.fonts = this.fonts || {};\n        var fontcopy = {\n                w: font.w,\n                face: {},\n                glyphs: {}\n            },\n            family = font.face[\"font-family\"];\n        for (var prop in font.face) if (font.face[has](prop)) {\n            fontcopy.face[prop] = font.face[prop];\n        }\n        if (this.fonts[family]) {\n            this.fonts[family].push(fontcopy);\n        } else {\n            this.fonts[family] = [fontcopy];\n        }\n        if (!font.svg) {\n            fontcopy.face[\"units-per-em\"] = toInt(font.face[\"units-per-em\"], 10);\n            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {\n                var path = font.glyphs[glyph];\n                fontcopy.glyphs[glyph] = {\n                    w: path.w,\n                    k: {},\n                    d: path.d && \"M\" + path.d.replace(/[mlcxtrv]/g, function (command) {\n                            return {l: \"L\", c: \"C\", x: \"z\", t: \"m\", r: \"l\", v: \"c\"}[command] || \"M\";\n                        }) + \"z\"\n                };\n                if (path.k) {\n                    for (var k in path.k) if (path[has](k)) {\n                        fontcopy.glyphs[glyph].k[k] = path.k[k];\n                    }\n                }\n            }\n        }\n        return font;\n    };\n    /*\\\n     * Paper.getFont\n     [ method ]\n     **\n     * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like “Myriad” for “Myriad Pro”.\n     **\n     > Parameters\n     **\n     - family (string) font family name or any word from it\n     - weight (string) #optional font weight\n     - style (string) #optional font style\n     - stretch (string) #optional font stretch\n     = (object) the font object\n     > Usage\n     | paper.print(100, 100, \"Test string\", paper.getFont(\"Times\", 800), 30);\n    \\*/\n    paperproto.getFont = function (family, weight, style, stretch) {\n        stretch = stretch || \"
57590normal\";\n        style = style || \"normal\";\n        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;\n        if (!R.fonts) {\n            return;\n        }\n        var font = R.fonts[family];\n        if (!font) {\n            var name = new RegExp(\"(^|\\\\s)\" + family.replace(/[^\\w\\d\\s+!~.:_-]/g, E) + \"(\\\\s|$)\", \"i\");\n            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {\n                if (name.test(fontName)) {\n                    font = R.fonts[fontName];\n                    break;\n                }\n            }\n        }\n        var thefont;\n        if (font) {\n            for (var i = 0, ii = font.length; i < ii; i++) {\n                thefont = font[i];\n                if (thefont.face[\"font-weight\"] == weight && (thefont.face[\"font-style\"] == style || !thefont.face[\"font-style\"]) && thefont.face[\"font-stretch\"] == stretch) {\n                    break;\n                }\n            }\n        }\n        return thefont;\n    };\n    /*\\\n     * Paper.print\n     [ method ]\n     **\n     * Creates path that represent given text written using given font at given position with given size.\n     * Result of the method is path element that contains whole text as a separate path.\n     **\n     > Parameters\n     **\n     - x (number) x position of the text\n     - y (number) y position of the text\n     - string (string) text to print\n     - font (object) font object, see @Paper.getFont\n     - size (number) #optional size of the font, default is `16`\n     - origin (string) #optional could be `\"baseline\"` or `\"middle\"`, default is `\"middle\"`\n     - letter_spacing (number) #optional number in range `-1..1`, default is `0`\n     - line_spacing (number) #optional number in range `1..3`, default is `1`\n     = (object) resulting path element, which consist of all letters\n     > Usage\n     | var txt = r.print(10, 50, \"print\", r.getFont(\"Museo\"), 30).attr({fill: \"#fff\"});\n    \\*/\n    paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) {\n        origin = origin || \"middle\"; // baseline|middle\n        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);\n        line_spacing = mmax(mmin(line_spacing || 1, 3), 1);\n        var letters = Str(string)[split](E),\n            shift = 0,\n            notfirst = 0,\n            path = E,\n            scale;\n        R.is(font, \"string\") && (font = this.getFont(font));\n        if (font) {\n            scale = (size || 16) / font.face[\"units-per-em\"];\n            var bb = font.face.bbox[split](separator),\n                top = +bb[0],\n                lineHeight = bb[3] - bb[1],\n                shifty = 0,\n                height = +bb[1] + (origin == \"baseline\" ? lineHeight + (+font.face.descent) : lineHeight / 2);\n            for (var i = 0, ii = letters.length; i < ii; i++) {\n                if (letters[i] == \"\\n\") {\n                    shift = 0;\n                    curr = 0;\n                    notfirst = 0;\n                    shifty += lineHeight * line_spacing;\n                } else {\n                    var prev = notfirst && font.glyphs[letters[i - 1]] || {},\n                        curr = font.glyphs[letters[i]];\n                    shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;\n                    notfirst = 1;\n                }\n                if (curr && curr.d) {\n                    path += R.transformPath(curr.d, [\"t\", shift * scale, shifty * scale, \"s\", scale, scale, top, height, \"t\", (x - top) / scale, (y - height) / scale]);\n                }\n            }\n        }\n        return this.path(path).attr({\n            fill: \"#000\",\n            stroke: \"none\"\n        });\n    };\n\n    /*\\\n     * Paper.add\n     [ method ]\n     **\n     * Imports elements in JSON array in format `{type: type, <attributes>}`\n     **\n     > Parameters\n     **\n     - json (array)\n     = (object) resulting set of imported elements\n     > Usage\n     | paper.add([\n     |     {\n     |         type: \"circle\",\n     |         cx: 10,\n     |         cy: 10,\n     |         r: 5\n     |     },\n     |     {\n     |         type: \"rect\",\n     |         x: 10,\n     |         y: 10,\n     |         width: 10,\n     |         height: 10,\n     |         fill: \"#fc0\"\n     |     }\n     | ]);\n    \\*/\n    paperproto.add = function (json) {\n        if (R.is(json, \"array\")) {\n            var res = this.set(),\n                i = 0,\n                ii = json.length,\n                j;\n            for (; i < ii;
57590 i++) {\n                j = json[i] || {};\n                elements[has](j.type) && res.push(this[j.type]().attr(j));\n            }\n        }\n        return res;\n    };\n\n    /*\\\n     * Raphael.format\n     [ method ]\n     **\n     * Simple format function. Replaces construction of type “`{<number>}`” to the corresponding argument.\n     **\n     > Parameters\n     **\n     - token (string) string to format\n     - … (string) rest of arguments will be treated as parameters for replacement\n     = (string) formated string\n     > Usage\n     | var x = 10,\n     |     y = 20,\n     |     width = 40,\n     |     height = 50;\n     | // this will draw a rectangular shape equivalent to \"M10,20h40v50h-40z\"\n     | paper.path(Raphael.format(\"M{0},{1}h{2}v{3}h{4}z\", x, y, width, height, -width));\n    \\*/\n    R.format = function (token, params) {\n        var args = R.is(params, array) ? [0][concat](params) : arguments;\n        token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {\n            return args[++i] == null ? E : args[i];\n        }));\n        return token || E;\n    };\n    /*\\\n     * Raphael.fullfill\n     [ method ]\n     **\n     * A little bit more advanced format function than @Raphael.format. Replaces construction of type “`{<name>}
57590`” to the corresponding argument.\n     **\n     > Parameters\n     **\n     - token (string) string to format\n     - json (object) object which properties will be used as a replacement\n     = (string) formated string\n     > Usage\n     | // this will draw a rectangular shape equivalent to \"M10,20h40v50h-40z\"\n     | paper.path(Raphael.fullfill(\"M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z\", {\n     |     x: 10,\n     |     y: 20,\n     |     dim: {\n     |         width: 40,\n     |         height: 50,\n     |         \"negative width\": -40\n     |     }\n     | }));\n    \\*/\n    R.fullfill = (function () {\n        var tokenRegex = /\\{([^\\}]+)\\}/g,\n            objNotationRegex = /(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g, // matches .xxxxx or [\"xxxxx\"] to run over object properties\n            replacer = function (all, key, obj) {\n                var res = obj;\n                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {\n                    name = name || quotedName;\n                    if (res) {\n                        if (name in res) {\n                            res = res[name];\n                        }\n                        typeof res == \"function\" && isFunc && (res = res());\n                    }\n                });\n                res = (res == null || res == obj ? all : res) + \"\";\n                return res;\n            };\n        return function (str, obj) {\n            return String(str).replace(tokenRegex, function (all, key) {\n                return replacer(all, key, obj);\n            });\n        };\n    })();\n    /*\\\n     * Raphael.ninja\n     [ method ]\n     **\n     * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method.\n     * Beware, that in this case plugins could stop working, because they are depending on global variable existence.\n     **\n     = (object) Raphael object\n     > Usage\n     | (function (local_raphael) {\n     |     var paper = local_raphael(10, 10, 320, 200);\n     |     …\n     | })(Raphael.ninja());\n    \\*/\n    R.ninja = function () {\n        if (oldRaphael.was) {\n            g.win.Raphael = oldRaphael.is;\n        } else {\n            // IE8 raises an error when deleting window property\n            window.Raphael = undefined;\n            try {\n                delete window.Raphael;\n            } catch(e) {}\n        }\n        return R;\n    };\n    /*\\\n     * Raphael.st\n     [ property (object) ]\n     **\n     * You can add your own method to elements and sets. It is wise to add a set method for each element method\n     * you added, so you will be able to call the same method on sets too.\n     **\n     * See also @Raphael.el.\n     > Usage\n     | Raphael.el.red = function () {\n     |     this.attr({fill: \"#f00\"});\n     | };\n     | Raphael.st.red = function () {\n     |     this.forEach(function (el) {\n     |         el.red();\n     |     });\n     | };\n     | // then use it\n     | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red();\n    \\*/\n    R.st = setproto;\n\n    eve.on(\"raphael.DOMload\", function () {\n        loaded = true;\n    });\n\n    // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html\n    (function (doc, loaded, f) {\n        if (doc.readyState == null && doc.addEventListener){\n            doc.addEventListener(loaded, f = function () {\n                doc.removeEventListener(loaded, f, false);\n                doc.readyState = \"complete\";\n            }, false);\n            doc.readyState = \"loading\";\n        }\n        function isLoaded() {\n            (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve(\"raphael.DOMload\");\n        }\n        isLoaded();\n    })(document, \"DOMContentLoaded\");\n\n    return R;\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC5jb3JlLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vUmFwaGFlbC8uL2Rldi9yYXBoYWVsLmNvcmUuanM/OTRkOSJdLCJzb3VyY2VzQ29udGVudCI6WyJkZWZpbmUoW1wiZXZlXCJdLCBmdW5jdGlvbihldmUpIHtcblxuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIGEgY2FudmFzIG9iamVjdCBvbiB3aGljaCB0byBkcmF3LlxuICAgICAqIFlvdSBtdXN0IGRvIHRoaXMgZmlyc3QsIGFzIGFsbCBmdXR1cmUgY2FsbHMgdG8gZHJhd2luZyBtZXRob2RzXG4gICAgICogZnJvbSB0aGlzIGluc3RhbmNlIHdpbGwgYmUgYm91bmQgdG8gdGhpcyBjYW52YXMuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGNvbnRhaW5lciAoSFRNTEVsZW1lbnR8c3RyaW5nKSBET00gZWxlbWVudCBvciBpdHMgSUQgd2hpY2ggaXMgZ29pbmcgdG8gYmUgYSBwYXJlbnQgZm9yIGRyYXdpbmcgc3VyZmFjZVxuICAgICAtIHdpZHRoIChudW1iZXIpXG4gICAgIC0gaGVpZ2h0IChudW1iZXIpXG4gICAgIC0gY2FsbGJhY2sgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgY2FsbGJhY2sgZnVuY3Rpb24gd2hpY2ggaXMgZ29pbmcgdG8gYmUgZXhlY3V0ZWQgaW4gdGhlIGNvbnRleHQgb2YgbmV3bHkgY3JlYXRlZCBwYXBlclxuICAgICAqIG9yXG4gICAgIC0geCAobnVtYmVyKVxuICAgICAtIHkgKG51bWJlcilcbiAgICAgLSB3aWR0aCAobnVtYmVyKVxuICAgICAtIGhlaWdodCAobnVtYmVyKVxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uIHdoaWNoIGlzIGdvaW5nIHRvIGJlIGV4ZWN1dGVkIGluIHRoZSBjb250ZXh0IG9mIG5ld2x5IGNyZWF0ZWQgcGFwZXJcbiAgICAgKiBvclxuICAgICAtIGFsbCAoYXJyYXkpIChmaXJzdCAzIG9yIDQgZWxlbWVudHMgaW4gdGhlIGFycmF5IGFyZSBlcXVhbCB0byBbY29udGFpbmVySUQsIHdpZHRoLCBoZWlnaHRdIG9yIFt4LCB5LCB3aWR0aCwgaGVpZ2h0XS4gVGhlIHJlc3QgYXJlIGVsZW1lbnQgZGVzY3JpcHRpb25zIGluIGZvcm1hdCB7dHlwZTogdHlwZSwgPGF0dHJpYnV0ZXM+fSkuIFNlZSBAUGFwZXIuYWRkLlxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uIHdoaWNoIGlzIGdvaW5nIHRvIGJlIGV4ZWN1dGVkIGluIHRoZSBjb250ZXh0IG9mIG5ld2x5IGNyZWF0ZWQgcGFwZXJcbiAgICAgKiBvclxuICAgICAtIG9uUmVhZHlDYWxsYmFjayAoZnVuY3Rpb24pIGZ1bmN0aW9uIHRoYXQgaXMgZ29pbmcgdG8gYmUgY2FsbGVkIG9uIERPTSByZWFkeSBldmVudC4gWW91IGNhbiBhbHNvIHN1YnNjcmliZSB0byB0aGlzIGV2ZW50IHZpYSBFdmXigJlzIOKAnERPTUxvYWTigJ0gZXZlbnQuIEluIHRoaXMgY2FzZSBtZXRob2QgcmV0dXJucyBgdW5kZWZpbmVkYC5cbiAgICAgPSAob2JqZWN0KSBAUGFwZXJcbiAgICAgPiBVc2FnZVxuICAgICB8IC8vIEVhY2ggb2YgdGhlIGZvbGxvd2luZyBleGFtcGxlcyBjcmVhdGUgYSBjYW52YXNcbiAgICAgfCAvLyB0aGF0IGlzIDMyMHB4IHdpZGUgYnkgMjAwcHggaGlnaC5cbiAgICAgfCAvLyBDYW52YXMgaXMgY3JlYXRlZCBhdCB0aGUgdmlld3BvcnTigJlzIDEwLDUwIGNvb3JkaW5hdGUuXG4gICAgI
57590HwgdmFyIHBhcGVyID0gUmFwaGFlbCgxMCwgNTAsIDMyMCwgMjAwKTtcbiAgICAgfCAvLyBDYW52YXMgaXMgY3JlYXRlZCBhdCB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSAjbm90ZXBhZCBlbGVtZW50XG4gICAgIHwgLy8gKG9yIGl0cyB0b3AgcmlnaHQgY29ybmVyIGluIGRpcj1cInJ0bFwiIGVsZW1lbnRzKVxuICAgICB8IHZhciBwYXBlciA9IFJhcGhhZWwoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJub3RlcGFkXCIpLCAzMjAsIDIwMCk7XG4gICAgIHwgLy8gU2FtZSBhcyBhYm92ZVxuICAgICB8IHZhciBwYXBlciA9IFJhcGhhZWwoXCJub3RlcGFkXCIsIDMyMCwgMjAwKTtcbiAgICAgfCAvLyBJbWFnZSBkdW1wXG4gICAgIHwgdmFyIHNldCA9IFJhcGhhZWwoW1wibm90ZXBhZFwiLCAzMjAsIDIwMCwge1xuICAgICB8ICAgICB0eXBlOiBcInJlY3RcIixcbiAgICAgfCAgICAgeDogMTAsXG4gICAgIHwgICAgIHk6IDEwLFxuICAgICB8ICAgICB3aWR0aDogMjUsXG4gICAgIHwgICAgIGhlaWdodDogMjUsXG4gICAgIHwgICAgIHN0cm9rZTogXCIjZjAwXCJcbiAgICAgfCB9LCB7XG4gICAgIHwgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICB8ICAgICB4OiAzMCxcbiAgICAgfCAgICAgeTogNDAsXG4gICAgIHwgICAgIHRleHQ6IFwiRHVtcFwiXG4gICAgIHwgfV0pO1xuICAgIFxcKi9cbiAgICBmdW5jdGlvbiBSKGZpcnN0KSB7XG4gICAgICAgIGlmIChSLmlzKGZpcnN0LCBcImZ1bmN0aW9uXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9hZGVkID8gZmlyc3QoKSA6IGV2ZS5vbihcInJhcGhhZWwuRE9NbG9hZFwiLCBmaXJzdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoUi5pcyhmaXJzdCwgYXJyYXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gUi5fZW5naW5lLmNyZWF0ZVthcHBseV0oUiwgZmlyc3Quc3BsaWNlKDAsIDMgKyBSLmlzKGZpcnN0WzBdLCBudSkpKS5hZGQoZmlyc3QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICAgICAgaWYgKFIuaXMoYXJnc1thcmdzLmxlbmd0aCAtIDFdLCBcImZ1bmN0aW9uXCIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGYgPSBhcmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkZWQgPyBmLmNhbGwoUi5fZW5naW5lLmNyZWF0ZVthcHBseV0oUiwgYXJncykpIDogZXZlLm9uKFwicmFwaGFlbC5ET01sb2FkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgZi5jYWxsKFIuX2VuZ2luZS5jcmVhdGVbYXBwbHldKFIsIGFyZ3MpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFIuX2VuZ2luZS5jcmVhdGVbYXBwbHldKFIsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgUi52ZXJzaW9uID0gXCIyLjIuMFwiO1xuICAgIFIuZXZlID0gZXZlO1xuICAgIHZhciBsb2FkZWQsXG4gICAgICAgIHNlcGFyYXRvciA9IC9bLCBdKy8sXG4gICAgICAgIGVsZW1lbnRzID0ge2NpcmNsZTogMSwgcmVjdDogMSwgcGF0aDogMSwgZWxsaXBzZTogMSwgdGV4dDogMSwgaW1hZ2U6IDF9LFxuICAgICAgICBmb3JtYXRyZyA9IC9cXHsoXFxkKylcXH0vZyxcbiAgICAgICAgcHJvdG8gPSBcInByb3RvdHlwZVwiLFxuICAgICAgICBoYXMgPSBcImhhc093blByb3BlcnR5XCIsXG4gICAgICAgIGcgPSB7XG4gICAgICAgICAgICBkb2M6IGRvY3VtZW50LFxuICAgICAgICAgICAgd2luOiB3aW5kb3dcbiAgICAgICAgfSxcbiAgICAgICAgb2xkUmFwaGFlbCA9IHtcbiAgICAgICAgICAgIHdhczogT2JqZWN0LnByb3RvdHlwZVtoYXNdLmNhbGwoZy53aW4sIFwiUmFwaGFlbFwiKSxcbiAgICAgICAgICAgIGlzOiBnLndpbi5SYXBoYWVsXG4gICAgICAgIH0sXG4gICAgICAgIFBhcGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLypcXFxuICAgICAgICAgICAgICogUGFwZXIuY2FcbiAgICAgICAgICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgICAgICAgICAqKlxuICAgICAgICAgICAgICogU2hvcnRjdXQgZm9yIEBQYXBlci5jdXN0b21BdHRyaWJ1dGVzXG4gICAgICAgICAgICBcXCovXG4gICAgICAgICAgICAvKlxcXG4gICAgICAgICAgICAgKiBQYXBlci5jdXN0b21BdHRyaWJ1dGVzXG4gICAgICAgICAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICAgICAgICAgKipcbiAgICAgICAgICAgICAqIElmIHlvdSBoYXZlIGEgc2V0IG9mIGF0dHJpYnV0ZXMgdGhhdCB5b3Ugd291bGQgbGlrZSB0byByZXByZXNlbnRcbiAgICAgICAgICAgICAqIGFzIGEgZnVuY3Rpb24gb2Ygc29tZSBudW1iZXIgeW91IGNhbiBkbyBpdCBlYXNpbHkgd2l0aCBjdXN0b20gYXR0cmlidXRlczpcbiAgICAgICAgICAgICA+IFVzYWdlXG4gICAgICAgICAgICAgfCBwYXBlci5jdXN0b21BdHRyaWJ1dGVzLmh1ZSA9IGZ1bmN0aW9uIChudW0pIHtcbiAgICAgICAgICAgICB8ICAgICBudW0gPSBudW0gJSAxO1xuICAgICAgICAgICAgIHwgICAgIHJldHVybiB7ZmlsbDogXCJoc2IoXCIgKyBudW0gKyBcIiwgMC43NSwgMSlcIn07XG4gICAgICAgICAgICAgfCB9O1xuICAgICAgICAgICAgIHwgLy8gQ3VzdG9tIGF0dHJpYnV0ZSDigJxodWXigJ0gd2lsbCBjaGFuZ2UgZmlsbFxuICAgICAgICAgICAgIHwgLy8gdG8gYmUgZ2l2ZW4gaHVlIHdpdGggZml4ZWQgc2F0dXJhdGlvbiBhbmQgYnJpZ2h0bmVzcy5cbiAgICAgICAgICAgICB8IC8vIE5vdyB5b3UgY2FuIHVzZSBpdCBsaWtlIHRoaXM6XG4gICAgICAgICAgICAgfCB2YXIgYyA9IHBhcGVyLmNpcmNsZSgxMCwgMTAsIDEwKS5hdHRyKHtodWU6IC40NX0pO1xuICAgICAgICAgICAgIHwgLy8gb3IgZXZlbiBsaWtlIHRoaXM6XG4gICAgICAgICAgICAgfCBjLmFuaW1hdGUoe2h1ZTogMX0sIDFlMyk7XG4gICAgICAgICAgICAgfFxuICAgICAgICAgICAgIHwgLy8gWW91IGNvdWxkIGFsc28gY3JlYXRlIGN1c3RvbSBhdHRyaWJ1dGVcbiAgICAgICAgICAgICB8IC8vIHdpdGggbXVsdGlwbGUgcGFyYW1ldGVyczpcbiAgICAgICAgICAgICB8IHBhcGVyLmN1c3RvbUF0dHJpYnV0ZXMuaHNiID0gZnVuY3Rpb24gKGgsIHMsIGIpIHtcbiAgICAgICAgICAgICB8ICAgICByZXR1cm4ge2ZpbGw6IFwiaHNiKFwiICsgW2gsIHMsIGJdLmpvaW4oXCIsXCIpICsgXCIpXCJ9O1xuICAgICAgICAgICAgI
57590HwgfTtcbiAgICAgICAgICAgICB8IGMuYXR0cih7aHNiOiBcIjAuNSAuOCAxXCJ9KTtcbiAgICAgICAgICAgICB8IGMuYW5pbWF0ZSh7aHNiOiBbMSwgMCwgMC41XX0sIDFlMyk7XG4gICAgICAgICAgICBcXCovXG4gICAgICAgICAgICB0aGlzLmNhID0gdGhpcy5jdXN0b21BdHRyaWJ1dGVzID0ge307XG4gICAgICAgIH0sXG4gICAgICAgIHBhcGVycHJvdG8sXG4gICAgICAgIGFwcGVuZENoaWxkID0gXCJhcHBlbmRDaGlsZFwiLFxuICAgICAgICBhcHBseSA9IFwiYXBwbHlcIixcbiAgICAgICAgY29uY2F0ID0gXCJjb25jYXRcIixcbiAgICAgICAgLy90YWtlbiBmcm9tIE1vZGVybml6ciB0b3VjaCB0ZXN0OiBodHRwczovL2dpdGh1Yi5jb20vTW9kZXJuaXpyL01vZGVybml6ci9ibG9iL21hc3Rlci9mZWF0dXJlLWRldGVjdHMvdG91Y2hldmVudHMuanMjTDQwXG4gICAgICAgIHN1cHBvcnRzVG91Y2ggPSAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93KSB8fCB3aW5kb3cuVG91Y2hFdmVudCB8fCB3aW5kb3cuRG9jdW1lbnRUb3VjaCAmJiBkb2N1bWVudCBpbnN0YW5jZW9mIERvY3VtZW50VG91Y2gsXG4gICAgICAgIEUgPSBcIlwiLFxuICAgICAgICBTID0gXCIgXCIsXG4gICAgICAgIFN0ciA9IFN0cmluZyxcbiAgICAgICAgc3BsaXQgPSBcInNwbGl0XCIsXG4gICAgICAgIGV2ZW50cyA9IFwiY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNlbW92ZSBtb3VzZW91dCBtb3VzZW92ZXIgbW91c2V1cCB0b3VjaHN0YXJ0IHRvdWNobW92ZSB0b3VjaGVuZCB0b3VjaGNhbmNlbFwiW3NwbGl0XShTKSxcbiAgICAgICAgdG91Y2hNYXAgPSB7XG4gICAgICAgICAgICBtb3VzZWRvd246IFwidG91Y2hzdGFydFwiLFxuICAgICAgICAgICAgbW91c2Vtb3ZlOiBcInRvdWNobW92ZVwiLFxuICAgICAgICAgICAgbW91c2V1cDogXCJ0b3VjaGVuZFwiXG4gICAgICAgIH0sXG4gICAgICAgIGxvd2VyQ2FzZSA9IFN0ci5wcm90b3R5cGUudG9Mb3dlckNhc2UsXG4gICAgICAgIG1hdGggPSBNYXRoLFxuICAgICAgICBtbWF4ID0gbWF0aC5tYXgsXG4gICAgICAgIG1taW4gPSBtYXRoLm1pbixcbiAgICAgICAgYWJzID0gbWF0aC5hYnMsXG4gICAgICAgIHBvdyA9IG1hdGgucG93LFxuICAgICAgICBQSSA9IG1hdGguUEksXG4gICAgICAgIG51ID0gXCJudW1iZXJcIixcbiAgICAgICAgc3RyaW5nID0gXCJzdHJpbmdcIixcbiAgICAgICAgYXJyYXkgPSBcImFycmF5XCIsXG4gICAgICAgIHRvU3RyaW5nID0gXCJ0b1N0cmluZ1wiLFxuICAgICAgICBmaWxsU3RyaW5nID0gXCJmaWxsXCIsXG4gICAgICAgIG9iamVjdFRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyxcbiAgICAgICAgcGFwZXIgPSB7fSxcbiAgICAgICAgcHVzaCA9IFwicHVzaFwiLFxuICAgICAgICBJU1VSTCA9IFIuX0lTVVJMID0gL151cmxcXChbJ1wiXT8oLis/KVsnXCJdP1xcKSQvaSxcbiAgICAgICAgY29sb3VyUmVnRXhwID0gL15cXHMqKCgjW2EtZlxcZF17Nn0pfCgjW2EtZlxcZF17M30pfHJnYmE/XFwoXFxzKihbXFxkXFwuXSslP1xccyosXFxzKltcXGRcXC5dKyU/XFxzKixcXHMqW1xcZFxcLl0rJT8oPzpcXHMqLFxccypbXFxkXFwuXSslPyk/KVxccypcXCl8aHNiYT9cXChcXHMqKFtcXGRcXC5dKyg/OmRlZ3xcXHhiMHwlKT9cXHMqLFxccypbXFxkXFwuXSslP1xccyosXFxzKltcXGRcXC5dKyg/OiU/XFxzKixcXHMqW1xcZFxcLl0rKT8pJT9cXHMqXFwpfGhzbGE/XFwoXFxzKihbXFxkXFwuXSsoPzpkZWd8XFx4YjB8JSk/XFxzKixcXHMqW1xcZFxcLl0rJT9cXHMqLFxccypbXFxkXFwuXSsoPzolP1xccyosXFxzKltcXGRcXC5dKyk/KSU/XFxzKlxcKSlcXHMqJC9pLFxuICAgICAgICBpc25hbiA9IHtcIk5hTlwiOiAxLCBcIkluZmluaXR5XCI6IDEsIFwiLUluZmluaXR5XCI6IDF9LFxuICAgICAgICBiZXppZXJyZyA9IC9eKD86Y3ViaWMtKT9iZXppZXJcXCgoW14sXSspLChbXixdKyksKFteLF0rKSwoW15cXCldKylcXCkvLFxuICAgICAgICByb3VuZCA9IG1hdGgucm91bmQsXG4gICAgICAgIHNldEF0dHJpYnV0ZSA9IFwic2V0QXR0cmlidXRlXCIsXG4gICAgICAgIHRvRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgICB0b0ludCA9IHBhcnNlSW50LFxuICAgICAgICB1cHBlckNhc2UgPSBTdHIucHJvdG90eXBlLnRvVXBwZXJDYXNlLFxuICAgICAgICBhdmFpbGFibGVBdHRycyA9IFIuX2F2YWlsYWJsZUF0dHJzID0ge1xuICAgICAgICAgICAgXCJhcnJvdy1lbmRcIjogXCJub25lXCIsXG4gICAgICAgICAgICBcImFycm93LXN0YXJ0XCI6IFwibm9uZVwiLFxuICAgICAgICAgICAgYmx1cjogMCxcbiAgICAgICAgICAgIFwiY2xpcC1yZWN0XCI6IFwiMCAwIDFlOSAxZTlcIixcbiAgICAgICAgICAgIGN1cnNvcjogXCJkZWZhdWx0XCIsXG4gICAgICAgICAgICBjeDogMCxcbiAgICAgICAgICAgIGN5OiAwLFxuICAgICAgICAgICAgZmlsbDogXCIjZmZmXCIsXG4gICAgICAgICAgICBcImZpbGwtb3BhY2l0eVwiOiAxLFxuICAgICAgICAgICAgZm9udDogJzEwcHggXCJBcmlhbFwiJyxcbiAgICAgICAgICAgIFwiZm9udC1mYW1pbHlcIjogJ1wiQXJpYWxcIicsXG4gICAgICAgICAgICBcImZvbnQtc2l6ZVwiOiBcIjEwXCIsXG4gICAgICAgICAgICBcImZvbnQtc3R5bGVcIjogXCJub3JtYWxcIixcbiAgICAgICAgICAgIFwiZm9udC13ZWlnaHRcIjogNDAwLFxuICAgICAgICAgICAgZ3JhZGllbnQ6IDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDAsXG4gICAgICAgICAgICBocmVmOiBcImh0dHA6Ly9yYXBoYWVsanMuY29tL1wiLFxuICAgICAgICAgICAgXCJsZXR0ZXItc3BhY2luZ1wiOiAwLFxuICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgIHBhdGg6IFwiTTAsMFwiLFxuICAgICAgICAgICAgcjogMCxcbiAgICAgICAgICAgIHJ4OiAwLFxuICAgICAgICAgICAgcnk6IDAsXG4gICAgICAgICAgICBzcmM6IFwiXCIsXG4gICAgICAgICAgICBzdHJva2U6IFwiIzAwMFwiLFxuICAgICAgICAgICAgXCJzdHJva2UtZGFzaGFycmF5XCI6IFwiXCIsXG4gICAgICAgICAgICBcInN0cm9rZS1saW5lY2FwXCI6IFwiYnV0dFwiLFxuICAgICAgICAgICAgXCJzdHJva2UtbGluZWpvaW5cIjogXCJidXR0XCIsXG4gICAgICAgICAgICBcInN0cm9rZS1taXRlcmxpbWl0XCI6IDAsXG4gICAgICAgICAgICBcInN0cm9rZS1vcGFjaXR5XCI6IDEsXG4gICAgICAgICAgICBcInN0cm9rZS13aWR0aFwiOiAxLFxuICAgICAgICAgICAgdGFyZ2V0OiBcIl9ibGFua1wiLFxuICAgICAgICAgICAgXCJ0ZXh0LWFuY2hvclwiOiBcIm1pZGRsZVwiLFxuICAgICAgICAgICAgdGl0bGU6IFwiUmFwaGFlbFwiLFxuICAgICAgICAgICAgdHJhbnNmb3JtOiBcIlwiLFxuICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgIFwiY2xhc3NcIjogXCJcIlxuICAgICAgICB9LFxuICAgICAgICBhdmFpbGFibGVBbmltQXR0cnMgPSBSLl9hdmFpbGFibGVBbmltQXR0cnMgPSB7XG4gICAgICAgICAgICBibHVyOiBudSxcbiAgICAgICAgICAgIFwiY2xpcC1yZWN0XCI6IFwiY3N2XCIsXG4gICAgICAgICAgICBjeDogbnUsXG4gICAgICAgICAgICBjeTogbnUsXG4gICAgICAgICAgICBmaWxsOiBcImNvbG91clwiLFxuICAgICAgICAgICAgXCJmaWxsLW9wYWNpdHlcIjogbnUsXG4gICAgICAgICAgICBcImZvbnQtc2l6ZVwiOiBudSxcbiAgICAgICAgICAgIGhlaWdodDogbnUsXG4gICAgICAgICAgICBvcGFjaXR5OiBudSxcbiAgICAgICAgICAgI
57590HBhdGg6IFwicGF0aFwiLFxuICAgICAgICAgICAgcjogbnUsXG4gICAgICAgICAgICByeDogbnUsXG4gICAgICAgICAgICByeTogbnUsXG4gICAgICAgICAgICBzdHJva2U6IFwiY29sb3VyXCIsXG4gICAgICAgICAgICBcInN0cm9rZS1vcGFjaXR5XCI6IG51LFxuICAgICAgICAgICAgXCJzdHJva2Utd2lkdGhcIjogbnUsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IFwidHJhbnNmb3JtXCIsXG4gICAgICAgICAgICB3aWR0aDogbnUsXG4gICAgICAgICAgICB4OiBudSxcbiAgICAgICAgICAgIHk6IG51XG4gICAgICAgIH0sXG4gICAgICAgIHdoaXRlc3BhY2UgPSAvW1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5XS9nLFxuICAgICAgICBjb21tYVNwYWNlcyA9IC9bXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKixbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKi8sXG4gICAgICAgIGhzcmcgPSB7aHM6IDEsIHJnOiAxfSxcbiAgICAgICAgcDJzID0gLyw/KFthY2hsbXFyc3R2eHpdKSw/L2dpLFxuICAgICAgICBwYXRoQ29tbWFuZCA9IC8oW2FjaGxtcnFzdHZ6XSlbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjksXSooKC0/XFxkKlxcLj9cXGQqKD86ZVtcXC0rXT9cXGQrKT9bXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKiw/W1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5XSopKykvaWcsXG4gICAgICAgIHRDb21tYW5kID0gLyhbcnN0bV0pW1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5LF0qKCgtP1xcZCpcXC4/XFxkKig/OmVbXFwtK10/XFxkKyk/W1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5XSosP1tcXHgwOVxceDBhXFx4MGJcXHgwY1xceDBkXFx4MjBcXHhhMFxcdTE2ODBcXHUxODBlXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwM1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMGFcXHUyMDJmXFx1MjA1ZlxcdTMwMDBcXHUyMDI4XFx1MjAyOV0qKSspL2lnLFxuICAgICAgICBwYXRoVmFsdWVzID0gLygtP1xcZCpcXC4/XFxkKig/OmVbXFwtK10/XFxkKyk/KVtcXHgwOVxceDBhXFx4MGJcXHgwY1xceDBkXFx4MjBcXHhhMFxcdTE2ODBcXHUxODBlXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwM1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMGFcXHUyMDJmXFx1MjA1ZlxcdTMwMDBcXHUyMDI4XFx1MjAyOV0qLD9bXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKi9pZyxcbiAgICAgICAgcmFkaWFsX2dyYWRpZW50ID0gUi5fcmFkaWFsX2dyYWRpZW50ID0gL15yKD86XFwoKFteLF0rPylbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKixbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKihbXlxcKV0rPylcXCkpPy8sXG4gICAgICAgIGVsZGF0YSA9IHt9LFxuICAgICAgICBzb3J0QnlLZXkgPSBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGEua2V5IC0gYi5rZXk7XG4gICAgICAgIH0sXG4gICAgICAgIHNvcnRCeU51bWJlciA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gdG9GbG9hdChhKSAtIHRvRmxvYXQoYik7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1biA9IGZ1bmN0aW9uICgpIHt9LFxuICAgICAgICBwaXBlID0gZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgI
57590HJldHVybiB4O1xuICAgICAgICB9LFxuICAgICAgICByZWN0UGF0aCA9IFIuX3JlY3RQYXRoID0gZnVuY3Rpb24gKHgsIHksIHcsIGgsIHIpIHtcbiAgICAgICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtbXCJNXCIsIHggKyByLCB5XSwgW1wibFwiLCB3IC0gciAqIDIsIDBdLCBbXCJhXCIsIHIsIHIsIDAsIDAsIDEsIHIsIHJdLCBbXCJsXCIsIDAsIGggLSByICogMl0sIFtcImFcIiwgciwgciwgMCwgMCwgMSwgLXIsIHJdLCBbXCJsXCIsIHIgKiAyIC0gdywgMF0sIFtcImFcIiwgciwgciwgMCwgMCwgMSwgLXIsIC1yXSwgW1wibFwiLCAwLCByICogMiAtIGhdLCBbXCJhXCIsIHIsIHIsIDAsIDAsIDEsIHIsIC1yXSwgW1wielwiXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW1tcIk1cIiwgeCwgeV0sIFtcImxcIiwgdywgMF0sIFtcImxcIiwgMCwgaF0sIFtcImxcIiwgLXcsIDBdLCBbXCJ6XCJdXTtcbiAgICAgICAgfSxcbiAgICAgICAgZWxsaXBzZVBhdGggPSBmdW5jdGlvbiAoeCwgeSwgcngsIHJ5KSB7XG4gICAgICAgICAgICBpZiAocnkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJ5ID0gcng7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW1tcIk1cIiwgeCwgeV0sIFtcIm1cIiwgMCwgLXJ5XSwgW1wiYVwiLCByeCwgcnksIDAsIDEsIDEsIDAsIDIgKiByeV0sIFtcImFcIiwgcngsIHJ5LCAwLCAxLCAxLCAwLCAtMiAqIHJ5XSwgW1wielwiXV07XG4gICAgICAgIH0sXG4gICAgICAgIGdldFBhdGggPSBSLl9nZXRQYXRoID0ge1xuICAgICAgICAgICAgcGF0aDogZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsLmF0dHIoXCJwYXRoXCIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNpcmNsZTogZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGEgPSBlbC5hdHRycztcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxsaXBzZVBhdGgoYS5jeCwgYS5jeSwgYS5yKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbGxpcHNlOiBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgYSA9IGVsLmF0dHJzO1xuICAgICAgICAgICAgICAgIHJldHVybiBlbGxpcHNlUGF0aChhLmN4LCBhLmN5LCBhLnJ4LCBhLnJ5KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZWN0OiBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgYSA9IGVsLmF0dHJzO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWN0UGF0aChhLngsIGEueSwgYS53aWR0aCwgYS5oZWlnaHQsIGEucik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW1hZ2U6IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgIHZhciBhID0gZWwuYXR0cnM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlY3RQYXRoKGEueCwgYS55LCBhLndpZHRoLCBhLmhlaWdodCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGV4dDogZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJib3ggPSBlbC5fZ2V0QkJveCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWN0UGF0aChiYm94LngsIGJib3gueSwgYmJveC53aWR0aCwgYmJveC5oZWlnaHQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldCA6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJib3ggPSBlbC5fZ2V0QkJveCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWN0UGF0aChiYm94LngsIGJib3gueSwgYmJveC53aWR0aCwgYmJveC5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICAvKlxcXG4gICAgICAgICAqIFJhcGhhZWwubWFwUGF0aFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogVHJhbnNmb3JtIHRoZSBwYXRoIHN0cmluZyB3aXRoIGdpdmVuIG1hdHJpeC5cbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBwYXRoIChzdHJpbmcpIHBhdGggc3RyaW5nXG4gICAgICAgICAtIG1hdHJpeCAob2JqZWN0KSBzZWUgQE1hdHJpeFxuICAgICAgICAgPSAoc3RyaW5nKSB0cmFuc2Zvcm1lZCBwYXRoIHN0cmluZ1xuICAgICAgICBcXCovXG4gICAgICAgIG1hcFBhdGggPSBSLm1hcFBhdGggPSBmdW5jdGlvbiAocGF0aCwgbWF0cml4KSB7XG4gICAgICAgICAgICBpZiAoIW1hdHJpeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHgsIHksIGksIGosIGlpLCBqaiwgcGF0aGk7XG4gICAgICAgICAgICBwYXRoID0gcGF0aDJjdXJ2ZShwYXRoKTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gcGF0aC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGF0aGkgPSBwYXRoW2ldO1xuICAgICAgICAgICAgICAgIGZvciAoaiA9IDEsIGpqID0gcGF0aGkubGVuZ3RoOyBqIDwgamo7IGogKz0gMikge1xuICAgICAgICAgICAgICAgICAgICB4ID0gbWF0cml4LngocGF0aGlbal0sIHBhdGhpW2ogKyAxXSk7XG4gICAgICAgICAgICAgICAgICAgIHkgPSBtYXRyaXgueShwYXRoaVtqXSwgcGF0aGlbaiArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aGlbal0gPSB4O1xuICAgICAgICAgICAgICAgICAgICBwYXRoaVtqICsgMV0gPSB5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICB9O1xuXG4gICAgUi5fZyA9IGc7XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwudHlwZVxuICAgICBbIHByb3BlcnR5IChzdHJpbmcpIF1cbiAgICAgKipcbiAgICAgKiBDYW4gYmUg4oCcU1ZH4oCdLCDigJxWTUzigJ0gb3IgZW1wdHksIGRlcGVuZGluZyBvbiBicm93c2VyIHN1cHBvcnQuXG4gICAgXFwqL1xuICAgIFIudHlwZSA9IChnLndpbi5TVkdBbmdsZSB8fCBnLmRvYy5pbXBsZW1lbnRhdGlvbi5oYXNGZWF0dXJlKFwiaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNCYXNpY1N0cnVjdHVyZVwiLCBcIjEuMVwiKSA/IFwiU1ZHXCIgOiBcIlZNTFwiKTtcbiAgICBpZiAoUi50eXBlID09IFwiVk1MXCIpIHtcbiAgICAgICAgdmFyIGQgPSBnLmRvYy5jcmVhdGVFbGVtZW50KFwiZGl2XCIpLFxuICAgICAgICAgICAgYjtcbiAgICAgICAgZC5pbm5lckhUTUwgPSAnPHY6c2hhcGUgYWRqPVwiMVwiLz4nO1xuICAgICAgICBiID0gZC5maXJzdENoaWxkO1xuICAgICAgICBiLnN0eWxlLmJlaGF2aW9yID0gXCJ1cmwoI2RlZmF1bHQjVk1MKVwiO1xuICAgICAgICBpZiAoIShiICYmIHR5cGVvZiBiLmFkaiA9PSBcIm9iamVjdFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIChSLnR5cGUgPSBFKTtcbiAgICAgICAgfVxuICAgICAgICBkID0gbnVsbDtcbiAgICB9XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuc3ZnXG4gICAgIFsgcHJvcGVydHkgKGJvb2xlYW4pIF1cbiAgICAgKipcbiAgICAgKiBgdHJ1ZWAgaWYgYnJvd3NlciBzdXBwb3J0cyBTVkcuXG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnZtbFxuICAgICBbIHByb3BlcnR5IChib29sZWFuKSBdXG4gICAgICoqXG4gICAgICogYHRydWVgIGlmIGJyb3dzZXIgc3VwcG9ydHMgVk1MLlxuICAgIFxcKi9cbiAgICBSLnN2ZyA9ICEoUi52bWwgPSBSLnR5cGUgPT0gXCJWTUxcIik7XG4gICAgUi5fUGFwZXIgPSBQYXBlcjtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5mblxuICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgKipcbiAgICAgKiBZb3UgY2FuIGFkZCB5b3VyIG93biBtZXRob2QgdG8gdGhlIGNhbnZhcy4gRm9yIGV4YW1wbGUgaWYgeW91IHdhbnQgdG8gZHJhdyBhIHBpZSBjaGFydCxcbiAgICAgKiB5b3UgY2FuIGNyZWF0ZSB5b3VyIG93biBwaWUgY2hhcnQgZnVuY3Rpb24gYW5kIHNoaXAgaXQgYXMgYSBSYXBoYcOrbCBwbHVnaW4uIFRvIGRvIHRoaXNcbiAgICAgKiB5b3UgbmVlZCB0byBleHRlbmQgdGhlIGBSYXBoYWVsLmZuYCBvYmplY3QuIFlvdSBzaG91bGQgbW9kaWZ5IHRoZSBgZm5gIG9iamVjdCBiZWZvcmUgYVxuICAgICAqIFJhcGhhw6tsIGluc3RhbmNlIGlzIGNyZWF0ZWQsIG90aGVyd2lzZSBpdCB3aWxsIHRha2Ugbm8gZWZmZWN0LiBQbGVhc2Ugbm90ZSB0aGF0IHR
57590oZVxuICAgICAqIGFiaWxpdHkgZm9yIG5hbWVzcGFjZWQgcGx1Z2lucyB3YXMgcmVtb3ZlZCBpbiBSYXBoYWVsIDIuMC4gSXQgaXMgdXAgdG8gdGhlIHBsdWdpbiB0b1xuICAgICAqIGVuc3VyZSBhbnkgbmFtZXNwYWNpbmcgZW5zdXJlcyBwcm9wZXIgY29udGV4dC5cbiAgICAgPiBVc2FnZVxuICAgICB8IFJhcGhhZWwuZm4uYXJyb3cgPSBmdW5jdGlvbiAoeDEsIHkxLCB4MiwgeTIsIHNpemUpIHtcbiAgICAgfCAgICAgcmV0dXJuIHRoaXMucGF0aCggLi4uICk7XG4gICAgIHwgfTtcbiAgICAgfCAvLyBvciBjcmVhdGUgbmFtZXNwYWNlXG4gICAgIHwgUmFwaGFlbC5mbi5teXN0dWZmID0ge1xuICAgICB8ICAgICBhcnJvdzogZnVuY3Rpb24gKCkge+KApn0sXG4gICAgIHwgICAgIHN0YXI6IGZ1bmN0aW9uICgpIHvigKZ9LFxuICAgICB8ICAgICAvLyBldGPigKZcbiAgICAgfCB9O1xuICAgICB8IHZhciBwYXBlciA9IFJhcGhhZWwoMTAsIDEwLCA2MzAsIDQ4MCk7XG4gICAgIHwgLy8gdGhlbiB1c2UgaXRcbiAgICAgfCBwYXBlci5hcnJvdygxMCwgMTAsIDMwLCAzMCwgNSkuYXR0cih7ZmlsbDogXCIjZjAwXCJ9KTtcbiAgICAgfCBwYXBlci5teXN0dWZmLmFycm93KCk7XG4gICAgIHwgcGFwZXIubXlzdHVmZi5zdGFyKCk7XG4gICAgXFwqL1xuICAgIFIuZm4gPSBwYXBlcnByb3RvID0gUGFwZXIucHJvdG90eXBlID0gUi5wcm90b3R5cGU7XG4gICAgUi5faWQgPSAwO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmlzXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBIYW5kZnVsIG9mIHJlcGxhY2VtZW50cyBmb3IgYHR5cGVvZmAgb3BlcmF0b3IuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIG8gKOKApikgYW55IG9iamVjdCBvciBwcmltaXRpdmVcbiAgICAgLSB0eXBlIChzdHJpbmcpIG5hbWUgb2YgdGhlIHR5cGUsIGkuZS4g4oCcc3RyaW5n4oCdLCDigJxmdW5jdGlvbuKAnSwg4oCcbnVtYmVy4oCdLCBldGMuXG4gICAgID0gKGJvb2xlYW4pIGlzIGdpdmVuIHZhbHVlIGlzIG9mIGdpdmVuIHR5cGVcbiAgICBcXCovXG4gICAgUi5pcyA9IGZ1bmN0aW9uIChvLCB0eXBlKSB7XG4gICAgICAgIHR5cGUgPSBsb3dlckNhc2UuY2FsbCh0eXBlKTtcbiAgICAgICAgaWYgKHR5cGUgPT0gXCJmaW5pdGVcIikge1xuICAgICAgICAgICAgcmV0dXJuICFpc25hbltoYXNdKCtvKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PSBcImFycmF5XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBvIGluc3RhbmNlb2YgQXJyYXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICAodHlwZSA9PSBcIm51bGxcIiAmJiBvID09PSBudWxsKSB8fFxuICAgICAgICAgICAgICAgICh0eXBlID09IHR5cGVvZiBvICYmIG8gIT09IG51bGwpIHx8XG4gICAgICAgICAgICAgICAgKHR5cGUgPT0gXCJvYmplY3RcIiAmJiBvID09PSBPYmplY3QobykpIHx8XG4gICAgICAgICAgICAgICAgKHR5cGUgPT0gXCJhcnJheVwiICYmIEFycmF5LmlzQXJyYXkgJiYgQXJyYXkuaXNBcnJheShvKSkgfHxcbiAgICAgICAgICAgICAgICBvYmplY3RUb1N0cmluZy5jYWxsKG8pLnNsaWNlKDgsIC0xKS50b0xvd2VyQ2FzZSgpID09IHR5cGU7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGNsb25lKG9iaikge1xuICAgICAgICBpZiAodHlwZW9mIG9iaiA9PSBcImZ1bmN0aW9uXCIgfHwgT2JqZWN0KG9iaikgIT09IG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgcmVzID0gbmV3IG9iai5jb25zdHJ1Y3RvcjtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKG9ialtoYXNdKGtleSkpIHtcbiAgICAgICAgICAgIHJlc1trZXldID0gY2xvbmUob2JqW2tleV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuYW5nbGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgYW5nbGUgYmV0d2VlbiB0d28gb3IgdGhyZWUgcG9pbnRzXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHgxIChudW1iZXIpIHggY29vcmQgb2YgZmlyc3QgcG9pbnRcbiAgICAgLSB5MSAobnVtYmVyKSB5IGNvb3JkIG9mIGZpcnN0IHBvaW50XG4gICAgIC0geDIgKG51bWJlcikgeCBjb29yZCBvZiBzZWNvbmQgcG9pbnRcbiAgICAgLSB5MiAobnVtYmVyKSB5IGNvb3JkIG9mIHNlY29uZCBwb2ludFxuICAgICAtIHgzIChudW1iZXIpICNvcHRpb25hbCB4IGNvb3JkIG9mIHRoaXJkIHBvaW50XG4gICAgIC0geTMgKG51bWJlcikgI29wdGlvbmFsIHkgY29vcmQgb2YgdGhpcmQgcG9pbnRcbiAgICAgPSAobnVtYmVyKSBhbmdsZSBpbiBkZWdyZWVzLlxuICAgIFxcKi9cbiAgICBSLmFuZ2xlID0gZnVuY3Rpb24gKHgxLCB5MSwgeDIsIHkyLCB4MywgeTMpIHtcbiAgICAgICAgaWYgKHgzID09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciB4ID0geDEgLSB4MixcbiAgICAgICAgICAgICAgICB5ID0geTEgLSB5MjtcbiAgICAgICAgICAgIGlmICgheCAmJiAheSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICgxODAgKyBtYXRoLmF0YW4yKC15LCAteCkgKiAxODAgLyBQSSArIDM2MCkgJSAzNjA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUi5hbmdsZSh4MSwgeTEsIHgzLCB5MykgLSBSLmFuZ2xlKHgyLCB5MiwgeDMsIHkzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucmFkXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBUcmFuc2Zvcm0gYW5nbGUgdG8gcmFkaWFuc1xuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBkZWcgKG51bWJlcikgYW5nbGUgaW4gZGVncmVlc1xuICAgICA9IChudW1iZXIpIGFuZ2xlIGluIHJhZGlhbnMuXG4gICAgXFwqL1xuICAgIFIucmFkID0gZnVuY3Rpb24gKGRlZykge1xuICAgICAgICByZXR1cm4gZGVnICUgMzYwICogUEkgLyAxODA7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5kZWdcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFRyYW5zZm9ybSBhbmdsZSB0byBkZWdyZWVzXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHJhZCAobnVtYmVyKSBhbmdsZSBpbiByYWRpYW5zXG4gICAgID0gKG51bWJlcikgYW5nbGUgaW4gZGVncmVlcy5cbiAgICBcXCovXG4gICAgUi5kZWcgPSBmdW5jdGlvbiAocmFkKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kICgocmFkICogMTgwIC8gUEklIDM2MCkqIDEwMDApIC8gMTAwMDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnNuYXBUb1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogU25hcHMgZ2l2ZW4gdmFsdWUgdG8gZ2l2ZW4gZ3JpZC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gdmFsdWVzIChhcnJheXxudW1iZXIpIGdpdmVuIGFycmF5IG9mIHZhbHVlcyBvciBzdGVwIG9mIHRoZSBncmlkXG4gICAgIC0gdmFsdWUgKG51bWJlcikgdmFsdWUgdG8gYWRqdXN0XG4gICAgIC0gdG9sZXJhbmNlIChudW1iZXIpICNvcHRpb25hbCB0b2xlcmFuY2UgZm9yIHNuYXBwaW5nLiBEZWZhdWx0IGlzIGAxMGAuXG4gICAgID0gKG51bWJlcikgYWRqdXN0ZWQgdmFsdWUuXG4gICAgXFwqL1xuICAgIFIuc25hcFRvID0gZnVuY3Rpb24gKHZhbHVlcywgdmFsdWUsIHRvbGVyYW5jZSkge1xuICAgICAgICB0b2xlcmFuY2UgPSBSLmlzKHRvbGVyYW5jZSwgXCJmaW5pdGVcIikgPyB0b2xlcmFuY2UgOiAxMDtcbiAgICAgICAgaWYgKFIuaXModmFsdWVzLCBhcnJheSkpIHtcbiAgICAgICAgICAgIHZhciBpID0gdmFsdWVzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIGlmIChhYnModmFsdWVzW2ldIC0gdmFsdWUpIDw9IHRvbGVyYW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXMgPSArdmFsdWVzO1xuICAgICAgICAgICAgdmFyIHJlbSA9IHZhbHVlICUgdmFsdWVzO1xuICAgICAgICAgICAgaWYgKHJlbSA8IHRvbGVyYW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZSAtIHJlbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZW0gPiB2YWx1ZXMgLSB0b2xlcmFuY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUgLSByZW0gKyB2YWx1ZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5jcmVhdGVVVUlEXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIFJGQzQxMjIsIHZlcnNpb24gNCBJRFxuICAgIFxcKi9cbiAgICB2YXIgY3JlYXRlVVVJRCA9IFIuY3JlYXRlVVVJRCA9IChmdW5jdGlvbiAodXVpZFJlZ0V4LCB1dWlkUmVwbGFjZXIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcInh4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eFwiLnJlcGxhY2UodXVpZFJlZ0V4LCB1dWlkUmVwbGFjZXIpLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgIH07XG4gICAgfSkoL1t4eV0vZywgZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgdmFyIHIgPSBtYXRoLnJhbmRvbSgpICogMTYgfCAwLFxuICAgICAgICAgICAgdiA9IGMgPT0gXCJ4XCIgPyByIDogKHIgJiAzIHwgOCk7XG4gICAgICAgIHJldHVybiB2LnRvU3RyaW5nKDE2KTtcbiAgICB9KTtcblxuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnNldFdpbmRvd1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXNlZCB3aGVuIHlvdSBuZWVkIHRvIGRyYXcgaW4gYCZsdDtpZnJhbWU+YC4gU3dpdGNoZWQgd2luZG93IHRvIHRoZSBpZnJhbWUgb25lLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBuZXd3aW4gKHdpbmRvdykgbmV3IHdpbmRvdyBvYmplY3RcbiAgICBcXCovXG4gICAgUi5zZXRXaW5kb3cgPSBmdW5jdGlvbiAobmV3d2luKSB7XG4gICAgICAgIGV2ZShcInJhcGhhZWwuc2V0V2luZG93XCIsIFIsIGcud2luLCBuZXd3aW4pO1xuICAgICAgICBnLndpbiA9IG5ld3dpbjtcbiAgICAgICAgZy5kb2MgPSBnLndpbi5kb2N1bWVudDtcbiAgICAgICAgaWYgKFIuX2VuZ2luZS5pbml0V2luKSB7XG4gICAgICAgICAgICBSLl9lbmdpbmUuaW5pdFdpbihnLndpbik7XG4gICAgICAgI
57590H1cbiAgICB9O1xuICAgIHZhciB0b0hleCA9IGZ1bmN0aW9uIChjb2xvcikge1xuICAgICAgICBpZiAoUi52bWwpIHtcbiAgICAgICAgICAgIC8vIGh0dHA6Ly9kZWFuLmVkd2FyZHMubmFtZS93ZWJsb2cvMjAwOS8xMC9jb252ZXJ0LWFueS1jb2xvdXItdmFsdWUtdG8taGV4LWluLW1zaWUvXG4gICAgICAgICAgICB2YXIgdHJpbSA9IC9eXFxzK3xcXHMrJC9nO1xuICAgICAgICAgICAgdmFyIGJvZDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvY3VtID0gbmV3IEFjdGl2ZVhPYmplY3QoXCJodG1sZmlsZVwiKTtcbiAgICAgICAgICAgICAgICBkb2N1bS53cml0ZShcIjxib2R5PlwiKTtcbiAgICAgICAgICAgICAgICBkb2N1bS5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIGJvZCA9IGRvY3VtLmJvZHk7XG4gICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgICBib2QgPSBjcmVhdGVQb3B1cCgpLmRvY3VtZW50LmJvZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmFuZ2UgPSBib2QuY3JlYXRlVGV4dFJhbmdlKCk7XG4gICAgICAgICAgICB0b0hleCA9IGNhY2hlcihmdW5jdGlvbiAoY29sb3IpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBib2Quc3R5bGUuY29sb3IgPSBTdHIoY29sb3IpLnJlcGxhY2UodHJpbSwgRSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHJhbmdlLnF1ZXJ5Q29tbWFuZFZhbHVlKFwiRm9yZUNvbG9yXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9ICgodmFsdWUgJiAyNTUpIDw8IDE2KSB8ICh2YWx1ZSAmIDY1MjgwKSB8ICgodmFsdWUgJiAxNjcxMTY4MCkgPj4+IDE2KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiI1wiICsgKFwiMDAwMDAwXCIgKyB2YWx1ZS50b1N0cmluZygxNikpLnNsaWNlKC02KTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibm9uZVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGkgPSBnLmRvYy5jcmVhdGVFbGVtZW50KFwiaVwiKTtcbiAgICAgICAgICAgIGkudGl0bGUgPSBcIlJhcGhhXFx4ZWJsIENvbG91ciBQaWNrZXJcIjtcbiAgICAgICAgICAgIGkuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgZy5kb2MuYm9keS5hcHBlbmRDaGlsZChpKTtcbiAgICAgICAgICAgIHRvSGV4ID0gY2FjaGVyKGZ1bmN0aW9uIChjb2xvcikge1xuICAgICAgICAgICAgICAgIGkuc3R5bGUuY29sb3IgPSBjb2xvcjtcbiAgICAgICAgICAgICAgICByZXR1cm4gZy5kb2MuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShpLCBFKS5nZXRQcm9wZXJ0eVZhbHVlKFwiY29sb3JcIik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9IZXgoY29sb3IpO1xuICAgIH0sXG4gICAgaHNidG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcImhzYihcIiArIFt0aGlzLmgsIHRoaXMucywgdGhpcy5iXSArIFwiKVwiO1xuICAgIH0sXG4gICAgaHNsdG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcImhzbChcIiArIFt0aGlzLmgsIHRoaXMucywgdGhpcy5sXSArIFwiKVwiO1xuICAgIH0sXG4gICAgcmdidG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhleDtcbiAgICB9LFxuICAgIHByZXBhcmVSR0IgPSBmdW5jdGlvbiAociwgZywgYikge1xuICAgICAgICBpZiAoZyA9PSBudWxsICYmIFIuaXMociwgXCJvYmplY3RcIikgJiYgXCJyXCIgaW4gciAmJiBcImdcIiBpbiByICYmIFwiYlwiIGluIHIpIHtcbiAgICAgICAgICAgIGIgPSByLmI7XG4gICAgICAgICAgICBnID0gci5nO1xuICAgICAgICAgICAgciA9IHIucjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZyA9PSBudWxsICYmIFIuaXMociwgc3RyaW5nKSkge1xuICAgICAgICAgICAgdmFyIGNsciA9IFIuZ2V0UkdCKHIpO1xuICAgICAgICAgICAgciA9IGNsci5yO1xuICAgICAgICAgICAgZyA9IGNsci5nO1xuICAgICAgICAgICAgYiA9IGNsci5iO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyID4gMSB8fCBnID4gMSB8fCBiID4gMSkge1xuICAgICAgICAgICAgciAvPSAyNTU7XG4gICAgICAgICAgICBnIC89IDI1NTtcbiAgICAgICAgICAgIGIgLz0gMjU1O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtyLCBnLCBiXTtcbiAgICB9LFxuICAgIHBhY2thZ2VSR0IgPSBmdW5jdGlvbiAociwgZywgYiwgbykge1xuICAgICAgICByICo9IDI1NTtcbiAgICAgICAgZyAqPSAyNTU7XG4gICAgICAgIGIgKj0gMjU1O1xuICAgICAgICB2Y
57590XIgcmdiID0ge1xuICAgICAgICAgICAgcjogcixcbiAgICAgICAgICAgIGc6IGcsXG4gICAgICAgICAgICBiOiBiLFxuICAgICAgICAgICAgaGV4OiBSLnJnYihyLCBnLCBiKSxcbiAgICAgICAgICAgIHRvU3RyaW5nOiByZ2J0b1N0cmluZ1xuICAgICAgICB9O1xuICAgICAgICBSLmlzKG8sIFwiZmluaXRlXCIpICYmIChyZ2Iub3BhY2l0eSA9IG8pO1xuICAgICAgICByZXR1cm4gcmdiO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5jb2xvclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUGFyc2VzIHRoZSBjb2xvciBzdHJpbmcgYW5kIHJldHVybnMgb2JqZWN0IHdpdGggYWxsIHZhbHVlcyBmb3IgdGhlIGdpdmVuIGNvbG9yLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBjbHIgKHN0cmluZykgY29sb3Igc3RyaW5nIGluIG9uZSBvZiB0aGUgc3VwcG9ydGVkIGZvcm1hdHMgKHNlZSBAUmFwaGFlbC5nZXRSR0IpXG4gICAgID0gKG9iamVjdCkgQ29tYmluZWQgUkdCICYgSFNCIG9iamVjdCBpbiBmb3JtYXQ6XG4gICAgIG8ge1xuICAgICBvICAgICByIChudW1iZXIpIHJlZCxcbiAgICAgbyAgICAgZyAobnVtYmVyKSBncmVlbixcbiAgICAgbyAgICAgYiAobnVtYmVyKSBibHVlLFxuICAgICBvICAgICBoZXggKHN0cmluZykgY29sb3IgaW4gSFRNTC9DU1MgZm9ybWF0OiAj4oCi4oCi4oCi4oCi4oCi4oCiLFxuICAgICBvICAgICBlcnJvciAoYm9vbGVhbikgYHRydWVgIGlmIHN0cmluZyBjYW7igJl0IGJlIHBhcnNlZCxcbiAgICAgbyAgICAgaCAobnVtYmVyKSBodWUsXG4gICAgIG8gICAgIHMgKG51bWJlcikgc2F0dXJhdGlvbixcbiAgICAgbyAgICAgdiAobnVtYmVyKSB2YWx1ZSAoYnJpZ2h0bmVzcyksXG4gICAgIG8gICAgIGwgKG51bWJlcikgbGlnaHRuZXNzXG4gICAgIG8gfVxuICAgIFxcKi9cbiAgICBSLmNvbG9yID0gZnVuY3Rpb24gKGNscikge1xuICAgICAgICB2Y
57590XIgcmdiO1xuICAgICAgICBpZiAoUi5pcyhjbHIsIFwib2JqZWN0XCIpICYmIFwiaFwiIGluIGNsciAmJiBcInNcIiBpbiBjbHIgJiYgXCJiXCIgaW4gY2xyKSB7XG4gICAgICAgICAgICByZ2IgPSBSLmhzYjJyZ2IoY2xyKTtcbiAgICAgICAgICAgIGNsci5yID0gcmdiLnI7XG4gICAgICAgICAgICBjbHIuZyA9IHJnYi5nO1xuICAgICAgICAgICAgY2xyLmIgPSByZ2IuYjtcbiAgICAgICAgICAgIGNsci5oZXggPSByZ2IuaGV4O1xuICAgICAgICB9IGVsc2UgaWYgKFIuaXMoY2xyLCBcIm9iamVjdFwiKSAmJiBcImhcIiBpbiBjbHIgJiYgXCJzXCIgaW4gY2xyICYmIFwibFwiIGluIGNscikge1xuICAgICAgICAgICAgcmdiID0gUi5oc2wycmdiKGNscik7XG4gICAgICAgICAgICBjbHIuciA9IHJnYi5yO1xuICAgICAgICAgICAgY2xyLmcgPSByZ2IuZztcbiAgICAgICAgICAgIGNsci5iID0gcmdiLmI7XG4gICAgICAgICAgICBjbHIuaGV4ID0gcmdiLmhleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChSLmlzKGNsciwgXCJzdHJpbmdcIikpIHtcbiAgICAgICAgICAgICAgICBjbHIgPSBSLmdldFJHQihjbHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFIuaXMoY2xyLCBcIm9iamVjdFwiKSAmJiBcInJcIiBpbiBjbHIgJiYgXCJnXCIgaW4gY2xyICYmIFwiYlwiIGluIGNscikge1xuICAgICAgICAgICAgICAgIHJnYiA9IFIucmdiMmhzbChjbHIpO1xuICAgICAgICAgICAgICAgIGNsci5oID0gcmdiLmg7XG4gICAgICAgICAgICAgICAgY2xyLnMgPSByZ2IucztcbiAgICAgICAgICAgICAgICBjbHIubCA9IHJnYi5sO1xuICAgICAgICAgICAgICAgIHJnYiA9IFIucmdiMmhzYihjbHIpO1xuICAgICAgICAgICAgICAgIGNsci52ID0gcmdiLmI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNsciA9IHtoZXg6IFwibm9uZVwifTtcbiAgICAgICAgICAgICAgICBjbHIuciA9IGNsci5nID0gY2xyLmIgPSBjbHIuaCA9IGNsci5zID0gY2xyLnYgPSBjbHIubCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNsci50b1N0cmluZyA9IHJnYnRvU3RyaW5nO1xuICAgICAgICByZXR1cm4gY2xyO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuaHNiMnJnYlxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ29udmVydHMgSFNCIHZhbHVlcyB0byBSR0Igb2JqZWN0LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoIChudW1iZXIpIGh1ZVxuICAgICAtIHMgKG51bWJlcikgc2F0dXJhdGlvblxuICAgICAtIHYgKG51bWJlcikgdmFsdWUgb3IgYnJpZ2h0bmVzc1xuICAgICA9IChvYmplY3QpIFJHQiBvYmplY3QgaW4gZm9ybWF0OlxuICAgICBvIHtcbiAgICAgbyAgICAgciAobnVtYmVyKSByZWQsXG4gICAgIG8gICAgIGcgKG51bWJlcikgZ3JlZW4sXG4gICAgIG8gICAgIGIgKG51bWJlcikgYmx1ZSxcbiAgICAgbyAgICAgaGV4IChzdHJpbmcpIGNvbG9yIGluIEhUTUwvQ1NTIGZvcm1hdDogI+KAouKAouKAouKAouKAouKAolxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5oc2IycmdiID0gZnVuY3Rpb24gKGgsIHMsIHYsIG8pIHtcbiAgICAgICAgaWYgKHRoaXMuaXMoaCwgXCJvYmplY3RcIikgJiYgXCJoXCIgaW4gaCAmJiBcInNcIiBpbiBoICYmIFwiYlwiIGluIGgpIHtcbiAgICAgICAgICAgIHYgPSBoLmI7XG4gICAgICAgICAgICBzID0gaC5zO1xuICAgICAgICAgICAgbyA9IGgubztcbiAgICAgICAgICAgIGggPSBoLmg7XG4gICAgICAgIH1cbiAgICAgICAgaCAqPSAzNjA7XG4gICAgICAgIHZhciBSLCBHLCBCLCBYLCBDO1xuICAgICAgICBoID0gKGggJSAzNjApIC8gNjA7XG4gICAgICAgIEMgPSB2ICogcztcbiAgICAgICAgWCA9IEMgKiAoMSAtIGFicyhoICUgMiAtIDEpKTtcbiAgICAgICAgUiA9IEcgPSBCID0gdiAtIEM7XG5cbiAgICAgICAgaCA9IH5+aDtcbiAgICAgICAgUiArPSBbQywgWCwgMCwgMCwgWCwgQ11baF07XG4gICAgICAgIEcgKz0gW1gsIEMsIEMsIFgsIDAsIDBdW2hdO1xuICAgICAgICBCICs9IFswLCAwLCBYLCBDLCBDLCBYXVtoXTtcbiAgICAgICAgcmV0dXJuIHBhY2thZ2VSR0IoUiwgRywgQiwgbyk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5oc2wycmdiXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBIU0wgdmFsdWVzIHRvIFJHQiBvYmplY3QuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGggKG51bWJlcikgaHVlXG4gICAgIC0gcyAobnVtYmVyKSBzYXR1cmF0aW9uXG4gICAgIC0gbCAobnVtYmVyKSBsdW1pbm9zaXR5XG4gICAgID0gKG9iamVjdCkgUkdCIG9iamVjdCBpbiBmb3JtYXQ6XG4gICAgIG8ge1xuICAgICBvICAgICByIChudW1iZXIpIHJlZCxcbiAgICAgbyAgICAgZyAobnVtYmVyKSBncmVlbixcbiAgICAgbyAgICAgYiAobnVtYmVyKSBibHVlLFxuICAgICBvICAgICBoZXggKHN0cmluZykgY29sb3IgaW4gSFRNTC9DU1MgZm9ybWF0OiAj4oCi4oCi4oCi4oCi4oCi4oCiXG4gICAgIG8gfVxuICAgIFxcKi9cbiAgICBSLmhzbDJyZ2IgPSBmdW5jdGlvbiAoaCwgcywgbCwgbykge1xuICAgICAgICBpZiAodGhpcy5pcyhoLCBcIm9iamVjdFwiKSAmJiBcImhcIiBpbiBoICYmIFwic1wiIGluIGggJiYgXCJsXCIgaW4gaCkge1xuICAgICAgICAgICAgbCA9IGgubDtcbiAgICAgICAgICAgIHMgPSBoLnM7XG4gICAgICAgICAgICBoID0gaC5oO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoID4gMSB8fCBzID4gMSB8fCBsID4gMSkge1xuICAgICAgICAgICAgaCAvPSAzNjA7XG4gICAgICAgICAgICBzIC89IDEwMDtcbiAgICAgICAgICAgIGwgLz0gMTAwO1xuICAgICAgICB9XG4gICAgICAgIGggKj0gMzYwO1xuICAgICAgICB2Y
57590XIgUiwgRywgQiwgWCwgQztcbiAgICAgICAgaCA9IChoICUgMzYwKSAvIDYwO1xuICAgICAgICBDID0gMiAqIHMgKiAobCA8IC41ID8gbCA6IDEgLSBsKTtcbiAgICAgICAgWCA9IEMgKiAoMSAtIGFicyhoICUgMiAtIDEpKTtcbiAgICAgICAgUiA9IEcgPSBCID0gbCAtIEMgLyAyO1xuXG4gICAgICAgIGggPSB+fmg7XG4gICAgICAgIFIgKz0gW0MsIFgsIDAsIDAsIFgsIENdW2hdO1xuICAgICAgICBHICs9IFtYLCBDLCBDLCBYLCAwLCAwXVtoXTtcbiAgICAgICAgQiArPSBbMCwgMCwgWCwgQywgQywgWF1baF07XG4gICAgICAgIHJldHVybiBwYWNrYWdlUkdCKFIsIEcsIEIsIG8pO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucmdiMmhzYlxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ29udmVydHMgUkdCIHZhbHVlcyB0byBIU0Igb2JqZWN0LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSByIChudW1iZXIpIHJlZFxuICAgICAtIGcgKG51bWJlcikgZ3JlZW5cbiAgICAgLSBiIChudW1iZXIpIGJsdWVcbiAgICAgPSAob2JqZWN0KSBIU0Igb2JqZWN0IGluIGZvcm1hdDpcbiAgICAgbyB7XG4gICAgIG8gICAgIGggKG51bWJlcikgaHVlXG4gICAgIG8gICAgIHMgKG51bWJlcikgc2F0dXJhdGlvblxuICAgICBvICAgICBiIChudW1iZXIpIGJyaWdodG5lc3NcbiAgICAgbyB9XG4gICAgXFwqL1xuICAgIFIucmdiMmhzYiA9IGZ1bmN0aW9uIChyLCBnLCBiKSB7XG4gICAgICAgIGIgPSBwcmVwYXJlUkdCKHIsIGcsIGIpO1xuICAgICAgICByID0gYlswXTtcbiAgICAgICAgZyA9IGJbMV07XG4gICAgICAgIGIgPSBiWzJdO1xuXG4gICAgICAgIHZhciBILCBTLCBWLCBDO1xuICAgICAgICBWID0gbW1heChyLCBnLCBiKTtcbiAgICAgICAgQyA9IFYgLSBtbWluKHIsIGcsIGIpO1xuICAgICAgICBIID0gKEMgPT0gMCA/IG51bGwgOlxuICAgICAgICAgICAgIFYgPT0gciA/IChnIC0gYikgLyBDIDpcbiAgICAgICAgICAgICBWID09IGcgPyAoYiAtIHIpIC8gQyArIDIgOlxuICAgICAgICAgICAgICAgICAgICAgIChyIC0gZykgLyBDICsgNFxuICAgICAgICAgICAgKTtcbiAgICAgICAgSCA9ICgoSCArIDM2MCkgJSA2KSAqIDYwIC8gMzYwO1xuICAgICAgICBTID0gQyA9PSAwID8gMCA6IEMgLyBWO1xuICAgICAgICByZXR1cm4ge2g6IEgsIHM6IFMsIGI6IFYsIHRvU3RyaW5nOiBoc2J0b1N0cmluZ307XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5yZ2IyaHNsXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBSR0IgdmFsdWVzIHRvIEhTTCBvYmplY3QuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHIgKG51bWJlcikgcmVkXG4gICAgIC0gZyAobnVtYmVyKSBncmVlblxuICAgICAtIGIgKG51bWJlcikgYmx1ZVxuICAgICA9IChvYmplY3QpIEhTTCBvYmplY3QgaW4gZm9ybWF0OlxuICAgICBvIHtcbiAgICAgbyAgICAgaCAobnVtYmVyKSBodWVcbiAgICAgbyAgICAgcyAobnVtYmVyKSBzYXR1cmF0aW9uXG4gICAgIG8gICAgIGwgKG51bWJlcikgbHVtaW5vc2l0eVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5yZ2IyaHNsID0gZnVuY3Rpb24gKHIsIGcsIGIpIHtcbiAgICAgICAgYiA9IHByZXBhcmVSR0IociwgZywgYik7XG4gICAgICAgIHIgPSBiWzBdO1xuICAgICAgICBnID0gYlsxXTtcbiAgICAgICAgYiA9IGJbMl07XG5cbiAgICAgICAgdmFyIEgsIFMsIEwsIE0sIG0sIEM7XG4gICAgICAgIE0gPSBtbWF4KHIsIGcsIGIpO1xuICAgICAgICBtID0gbW1pbihyLCBnLCBiKTtcbiAgICAgICAgQyA9IE0gLSBtO1xuICAgICAgICBIID0gKEMgPT0gMCA/IG51bGwgOlxuICAgICAgICAgICAgIE0gPT0gciA/IChnIC0gYikgLyBDIDpcbiAgICAgICAgICAgICBNID09IGcgPyAoYiAtIHIpIC8gQyArIDIgOlxuICAgICAgICAgICAgICAgICAgICAgIChyIC0gZykgLyBDICsgNCk7XG4gICAgICAgIEggPSAoKEggKyAzNjApICUgNikgKiA2MCAvIDM2MDtcbiAgICAgICAgTCA9IChNICsgbSkgLyAyO1xuICAgICAgICBTID0gKEMgPT0gMCA/IDAgOlxuICAgICAgICAgICAgIEwgPCAuNSA/IEMgLyAoMiAqIEwpIDpcbiAgICAgICAgICAgICAgICAgICAgICBDIC8gKDIgLSAyICogTCkpO1xuICAgICAgICByZXR1cm4ge2g6IEgsIHM6IFMsIGw6IEwsIHRvU3RyaW5nOiBoc2x0b1N0cmluZ307XG4gICAgfTtcbiAgICBSLl9wYXRoMnN0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuam9pbihcIixcIikucmVwbGFjZShwMnMsIFwiJDFcIik7XG4gICAgfTtcbiAgICBmdW5jdGlvbiByZXB1c2goYXJyYXksIGl0ZW0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gYXJyYXkubGVuZ3RoOyBpIDwgaWk7IGkrKykgaWYgKGFycmF5W2ldID09PSBpdGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJyYXkucHVzaChhcnJheS5zcGxpY2UoaSwgMSlbMF0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNhY2hlcihmLCBzY29wZSwgcG9zdHByb2Nlc3Nvcikge1xuICAgICAgICBmdW5jdGlvbiBuZXdmKCkge1xuICAgICAgICAgICAgdmFyIGFyZyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCksXG4gICAgICAgICAgICAgICAgYXJncyA9IGFyZy5qb2luKFwiXFx1MjQwMFwiKSxcbiAgICAgICAgICAgICAgICBjYWNoZSA9IG5ld2YuY2FjaGUgPSBuZXdmLmNhY2hlIHx8IHt9LFxuICAgICAgICAgICAgICAgIGNvdW50ID0gbmV3Zi5jb3VudCA9IG5ld2YuY291bnQgfHwgW107XG4gICAgICAgICAgICBpZiAoY2FjaGVbaGFzXShhcmdzKSkge1xuICAgICAgICAgICAgICAgIHJlcHVzaChjb3VudCwgYXJncyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc3Rwcm9jZXNzb3IgPyBwb3N0cHJvY2Vzc29yKGNhY2hlW2FyZ3NdKSA6IGNhY2hlW2FyZ3NdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY291bnQubGVuZ3RoID49IDFlMyAmJiBkZWxldGUgY2FjaGVbY291bnQuc2hpZnQoKV07XG4gICAgICAgICAgICBjb3VudC5wdXNoKGFyZ3MpO1xuICAgICAgICAgICAgY2FjaGVbYXJnc10gPSBmW2FwcGx5XShzY29wZSwgYXJnKTtcbiAgICAgICAgICAgI
57590HJldHVybiBwb3N0cHJvY2Vzc29yID8gcG9zdHByb2Nlc3NvcihjYWNoZVthcmdzXSkgOiBjYWNoZVthcmdzXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3ZjtcbiAgICB9XG5cbiAgICB2YXIgcHJlbG9hZCA9IFIuX3ByZWxvYWQgPSBmdW5jdGlvbiAoc3JjLCBmKSB7XG4gICAgICAgIHZhciBpbWcgPSBnLmRvYy5jcmVhdGVFbGVtZW50KFwiaW1nXCIpO1xuICAgICAgICBpbWcuc3R5bGUuY3NzVGV4dCA9IFwicG9zaXRpb246YWJzb2x1dGU7bGVmdDotOTk5OWVtO3RvcDotOTk5OWVtXCI7XG4gICAgICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBmLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9ubG9hZCA9IG51bGw7XG4gICAgICAgICAgICBnLmRvYy5ib2R5LnJlbW92ZUNoaWxkKHRoaXMpO1xuICAgICAgICB9O1xuICAgICAgICBpbWcub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGcuZG9jLmJvZHkucmVtb3ZlQ2hpbGQodGhpcyk7XG4gICAgICAgIH07XG4gICAgICAgIGcuZG9jLmJvZHkuYXBwZW5kQ2hpbGQoaW1nKTtcbiAgICAgICAgaW1nLnNyYyA9IHNyYztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2xyVG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhleDtcbiAgICB9XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5nZXRSR0JcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFBhcnNlcyBjb2xvdXIgc3RyaW5nIGFzIFJHQiBvYmplY3RcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gY29sb3VyIChzdHJpbmcpIGNvbG91ciBzdHJpbmcgaW4gb25lIG9mIGZvcm1hdHM6XG4gICAgICMgPHVsPlxuICAgICAjICAgICA8bGk+Q29sb3VyIG5hbWUgKOKAnDxjb2RlPnJlZDwvY29kZT7igJ0sIOKAnDxjb2RlPmdyZWVuPC9jb2RlPuKAnSwg4oCcPGNvZGU+Y29ybmZsb3dlcmJsdWU8L2NvZGU+4oCdLCBldGMpPC9saT5cbiAgICAgIyAgICAgPGxpPiPigKLigKLigKIg4oCUIHNob3J0ZW5lZCBIVE1MIGNvbG91cjogKOKAnDxjb2RlPiMwMDA8L2NvZGU+4oCdLCDigJw8Y29kZT4jZmMwPC9jb2RlPuKAnSwgZXRjKTwvbGk+XG4gICAgICMgICAgIDxsaT4j4oCi4oCi4oCi4oCi4oCi4oCiIOKAlCBmdWxsIGxlbmd0aCBIVE1MIGNvbG91cjogKOKAnDxjb2RlPiMwMDAwMDA8L2NvZGU+4oCdLCDigJw8Y29kZT4jYmQyMzAwPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+cmdiKOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCByZWQsIGdyZWVuIGFuZCBibHVlIGNoYW5uZWxz4oCZIHZhbHVlczogKOKAnDxjb2RlPnJnYigyMDAsJm5ic3A7MTAwLCZuYnNwOzApPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+cmdiKOKAouKAouKAoiUsIOKAouKAouKAoiUsIOKAouKAouKAoiUpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgaW4gJTogKOKAnDxjb2RlPnJnYigxMDAlLCZuYnNwOzE3NSUsJm5ic3A7MCUpPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+aHNiKOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCBodWUsIHNhdHVyYXRpb24gYW5kIGJyaWdodG5lc3MgdmFsdWVzOiAo4oCcPGNvZGU+aHNiKDAuNSwmbmJzcDswLjI1LCZuYnNwOzEpPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+aHNiKOKAouKAouKAoiUsIOKAouKAouKAoiUsIOKAouKAouKAoiUpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgaW4gJTwvbGk+XG4gICAgICMgICAgIDxsaT5oc2wo4oCi4oCi4oCiLCDigKLigKLigKIsIOKAouKAouKAoikg4oCUIHNhbWUgYXMgaHNiPC9saT5cbiAgICAgIyAgICAgPGxpPmhzbCjigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBoc2I8L2xpPlxuICAgICAjIDwvdWw+XG4gICAgID0gKG9iamVjdCkgUkdCIG9iamVjdCBpbiBmb3JtYXQ6XG4gICAgIG8ge1xuICAgICBvICAgICByIChudW1iZXIpIHJlZCxcbiAgICAgbyAgICAgZyAobnVtYmVyKSBncmVlbixcbiAgICAgbyAgICAgYiAobnVtYmVyKSBibHVlXG4gICAgIG8gICAgIGhleCAoc3RyaW5nKSBjb2xvciBpbiBIVE1ML0NTUyBmb3JtYXQ6ICPigKLigKLigKLigKLigKLigKIsXG4gICAgIG8gICAgIGVycm9yIChib29sZWFuKSB0cnVlIGlmIHN0cmluZyBjYW7igJl0IGJlIHBhcnNlZFxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5nZXRSR0IgPSBjYWNoZXIoZnVuY3Rpb24gKGNvbG91cikge1xuICAgICAgICBpZiAoIWNvbG91ciB8fCAhISgoY29sb3VyID0gU3RyKGNvbG91cikpLmluZGV4T2YoXCItXCIpICsgMSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7cjogLTEsIGc6IC0xLCBiOiAtMSwgaGV4OiBcIm5vbmVcIiwgZXJyb3I6IDEsIHRvU3RyaW5nOiBjbHJUb1N0cmluZ307XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbG91ciA9PSBcIm5vbmVcIikge1xuICAgICAgICAgICAgcmV0dXJuIHtyOiAtMSwgZzogLTEsIGI6IC0xLCBoZXg6IFwibm9uZVwiLCB0b1N0cmluZzogY2xyVG9TdHJpbmd9O1xuICAgICAgICB9XG4gICAgICAgICEoaHNyZ1toYXNdKGNvbG91ci50b0xvd2VyQ2FzZSgpLnN1YnN0cmluZygwLCAyKSkgfHwgY29sb3VyLmNoYXJBdCgpID09IFwiI1wiKSAmJiAoY29sb3VyID0gdG9IZXgoY29sb3VyKSk7XG4gICAgICAgIHZhciByZXMsXG4gICAgICAgICAgICByZWQsXG4gICAgICAgICAgICBncmVlbixcbiAgICAgICAgICAgIGJsdWUsXG4gICAgICAgICAgICBvcGFjaXR5LFxuICAgICAgICAgICAgdCxcbiAgICAgICAgICAgIHZhbHVlcyxcbiAgICAgICAgICAgIHJnYiA9IGNvbG91ci5tYXRjaChjb2xvdXJSZWdFeHApO1xuICAgICAgICBpZiAocmdiKSB7XG4gICAgICAgICAgICBpZiAocmdiWzJdKSB7XG4gICAgICAgICAgICAgICAgYmx1ZSA9IHRvSW50KHJnYlsyXS5zdWJzdHJpbmcoNSksIDE2KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvSW50KHJnYlsyXS5zdWJzdHJpbmcoMywgNSksIDE2KTtcbiAgICAgICAgICAgICAgICByZWQgPSB0b0ludChyZ2JbMl0uc3Vic3RyaW5nKDEsIDMpLCAxNik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzNdKSB7XG4gICAgICAgICAgICAgICAgYmx1ZSA9IHRvSW50KCh0ID0gcmdiWzNdLmNoYXJBdCgzKSkgKyB0LCAxNik7XG4gICAgICAgICAgICAgICAgZ3JlZW4gPSB0b0ludCgodCA9IHJnYlszXS5jaGFyQXQoMikpICsgdCwgMTYpO1xuICAgICAgICAgICAgICAgI
57590HJlZCA9IHRvSW50KCh0ID0gcmdiWzNdLmNoYXJBdCgxKSkgKyB0LCAxNik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzRdKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzID0gcmdiWzRdW3NwbGl0XShjb21tYVNwYWNlcyk7XG4gICAgICAgICAgICAgICAgcmVkID0gdG9GbG9hdCh2YWx1ZXNbMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKHJlZCAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvRmxvYXQodmFsdWVzWzFdKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbMV0uc2xpY2UoLTEpID09IFwiJVwiICYmIChncmVlbiAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBibHVlID0gdG9GbG9hdCh2YWx1ZXNbMl0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1syXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKGJsdWUgKj0gMi41NSk7XG4gICAgICAgICAgICAgICAgcmdiWzFdLnRvTG93ZXJDYXNlKCkuc2xpY2UoMCwgNCkgPT0gXCJyZ2JhXCIgJiYgKG9wYWNpdHkgPSB0b0Zsb2F0KHZhbHVlc1szXSkpO1xuICAgICAgICAgICAgICAgIHZhbHVlc1szXSAmJiB2YWx1ZXNbM10uc2xpY2UoLTEpID09IFwiJVwiICYmIChvcGFjaXR5IC89IDEwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzVdKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzID0gcmdiWzVdW3NwbGl0XShjb21tYVNwYWNlcyk7XG4gICAgICAgICAgICAgICAgcmVkID0gdG9GbG9hdCh2YWx1ZXNbMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKHJlZCAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvRmxvYXQodmFsdWVzWzFdKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbMV0uc2xpY2UoLTEpID09IFwiJVwiICYmIChncmVlbiAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBibHVlID0gdG9GbG9hdCh2YWx1ZXNbMl0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1syXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKGJsdWUgKj0gMi41NSk7XG4gICAgICAgICAgICAgICAgKHZhbHVlc1swXS5zbGljZSgtMykgPT0gXCJkZWdcIiB8fCB2YWx1ZXNbMF0uc2xpY2UoLTEpID09IFwiXFx4YjBcIikgJiYgKHJlZCAvPSAzNjApO1xuICAgICAgICAgICAgICAgIHJnYlsxXS50b0xvd2VyQ2FzZSgpLnNsaWNlKDAsIDQpID09IFwiaHNiYVwiICYmIChvcGFjaXR5ID0gdG9GbG9hdCh2YWx1ZXNbM10pKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbM10gJiYgdmFsdWVzWzNdLnNsaWNlKC0xKSA9PSBcIiVcIiAmJiAob3BhY2l0eSAvPSAxMDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBSLmhzYjJyZ2IocmVkLCBncmVlbiwgYmx1ZSwgb3BhY2l0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzZdKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzID0gcmdiWzZdW3NwbGl0XShjb21tYVNwYWNlcyk7XG4gICAgICAgICAgICAgICAgcmVkID0gdG9GbG9hdCh2YWx1ZXNbMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKHJlZCAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvRmxvYXQodmFsdWVzWzFdKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbMV0uc2xpY2UoLTEpID09IFwiJVwiICYmIChncmVlbiAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBibHVlID0gdG9GbG9hdCh2YWx1ZXNbMl0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1syXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKGJsdWUgKj0gMi41NSk7XG4gICAgICAgICAgICAgICAgKHZhbHVlc1swXS5zbGljZSgtMykgPT0gXCJkZWdcIiB8fCB2YWx1ZXNbMF0uc2xpY2UoLTEpID09IFwiXFx4YjBcIikgJiYgKHJlZCAvPSAzNjApO1xuICAgICAgICAgICAgICAgIHJnYlsxXS50b0xvd2VyQ2FzZSgpLnNsaWNlKDAsIDQpID09IFwiaHNsYVwiICYmIChvcGFjaXR5ID0gdG9GbG9hdCh2YWx1ZXNbM10pKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbM10gJiYgdmFsdWVzWzNdLnNsaWNlKC0xKSA9PSBcIiVcIiAmJiAob3BhY2l0eSAvPSAxMDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBSLmhzbDJyZ2IocmVkLCBncmVlbiwgYmx1ZSwgb3BhY2l0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZ2IgPSB7cjogcmVkLCBnOiBncmVlbiwgYjogYmx1ZSwgdG9TdHJpbmc6IGNsclRvU3RyaW5nfTtcbiAgICAgICAgICAgIHJnYi5oZXggPSBcIiNcIiArICgxNjc3NzIxNiB8IGJsdWUgfCAoZ3JlZW4gPDwgOCkgfCAocmVkIDw8IDE2KSkudG9TdHJpbmcoMTYpLnNsaWNlKDEpO1xuICAgICAgICAgICAgUi5pcyhvcGFjaXR5LCBcImZpbml0ZVwiKSAmJiAocmdiLm9wYWNpdHkgPSBvcGFjaXR5KTtcbiAgICAgICAgICAgIHJldHVybiByZ2I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtyOiAtMSwgZzogLTEsIGI6IC0xLCBoZXg6IFwibm9uZVwiLCBlcnJvcjogMSwgdG9TdHJpbmc6IGNsclRvU3RyaW5nfTtcbiAgICB9LCBSKTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5oc2JcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENvbnZlcnRzIEhTQiB2YWx1ZXMgdG8gaGV4IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjb2xvdXIuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGggKG51bWJlcikgaHVlXG4gICAgIC0gcyAobnVtYmVyKSBzYXR1cmF0aW9uXG4gICAgIC0gYiAobnVtYmVyKSB2YWx1ZSBvciBicmlnaHRuZXNzXG4gICAgID0gKHN0cmluZykgaGV4IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjb2xvdXIuXG4gICAgXFwqL1xuICAgIFIuaHNiID0gY2FjaGVyKGZ1bmN0aW9uIChoLCBzLCBiKSB7XG4gICAgICAgIHJldHVybiBSLmhzYjJyZ2IoaCwgcywgYikuaGV4O1xuICAgIH0pO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmhzbFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ29udmVydHMgSFNMIHZhbHVlcyB0byBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGNvbG91ci5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaCAobnVtYmVyKSBodWVcbiAgICAgLSBzIChudW1iZXIpIHNhdHVyYXRpb25cbiAgICAgLSBsIChudW1iZXIpIGx1bWlub3NpdHlcbiAgICAgPSAoc3RyaW5nKSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGNvbG91ci5cbiAgICBcXCovXG4gICAgUi5oc2wgPSBjYWNoZXIoZnVuY3Rpb24gKGgsIHMsIGwpIHtcbiAgICAgICAgcmV0dXJuIFIuaHNsMnJnYihoLCBzLCBsKS5oZXg7XG4gICAgfSk7XG4gICAgLypcXFxuICAgICAqIFJhcGh
57590hZWwucmdiXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBSR0IgdmFsdWVzIHRvIGhleCByZXByZXNlbnRhdGlvbiBvZiB0aGUgY29sb3VyLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSByIChudW1iZXIpIHJlZFxuICAgICAtIGcgKG51bWJlcikgZ3JlZW5cbiAgICAgLSBiIChudW1iZXIpIGJsdWVcbiAgICAgPSAoc3RyaW5nKSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGNvbG91ci5cbiAgICBcXCovXG4gICAgUi5yZ2IgPSBjYWNoZXIoZnVuY3Rpb24gKHIsIGcsIGIpIHtcbiAgICAgICAgZnVuY3Rpb24gcm91bmQoeCkgeyByZXR1cm4gKHggKyAwLjUpIHwgMDsgfVxuICAgICAgICByZXR1cm4gXCIjXCIgKyAoMTY3NzcyMTYgfCByb3VuZChiKSB8IChyb3VuZChnKSA8PCA4KSB8IChyb3VuZChyKSA8PCAxNikpLnRvU3RyaW5nKDE2KS5zbGljZSgxKTtcbiAgICB9KTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5nZXRDb2xvclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogT24gZWFjaCBjYWxsIHJldHVybnMgbmV4dCBjb2xvdXIgaW4gdGhlIHNwZWN0cnVtLiBUbyByZXNldCBpdCBiYWNrIHRvIHJlZCBjYWxsIEBSYXBoYWVsLmdldENvbG9yLnJlc2V0XG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHZhbHVlIChudW1iZXIpICNvcHRpb25hbCBicmlnaHRuZXNzLCBkZWZhdWx0IGlzIGAwLjc1YFxuICAgICA9IChzdHJpbmcpIGhleCByZXByZXNlbnRhdGlvbiBvZiB0aGUgY29sb3VyLlxuICAgIFxcKi9cbiAgICBSLmdldENvbG9yID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBzdGFydCA9IHRoaXMuZ2V0Q29sb3Iuc3RhcnQgPSB0aGlzLmdldENvbG9yLnN0YXJ0IHx8IHtoOiAwLCBzOiAxLCBiOiB2YWx1ZSB8fCAuNzV9LFxuICAgICAgICAgICAgcmdiID0gdGhpcy5oc2IycmdiKHN0YXJ0LmgsIHN0YXJ0LnMsIHN0YXJ0LmIpO1xuICAgICAgICBzdGFydC5oICs9IC4wNzU7XG4gICAgICAgIGlmIChzdGFydC5oID4gMSkge1xuICAgICAgICAgICAgc3RhcnQuaCA9IDA7XG4gICAgICAgICAgICBzdGFydC5zIC09IC4yO1xuICAgICAgICAgICAgc3RhcnQucyA8PSAwICYmICh0aGlzLmdldENvbG9yLnN0YXJ0ID0ge2g6IDAsIHM6IDEsIGI6IHN0YXJ0LmJ9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmdiLmhleDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmdldENvbG9yLnJlc2V0XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXNldHMgc3BlY3RydW0gcG9zaXRpb24gZm9yIEBSYXBoYWVsLmdldENvbG9yIGJhY2sgdG8gcmVkLlxuICAgIFxcKi9cbiAgICBSLmdldENvbG9yLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBkZWxldGUgdGhpcy5zdGFydDtcbiAgICB9O1xuXG4gICAgLy8gaHR0cDovL3NjaGVwZXJzLmNjL2dldHRpbmctdG8tdGhlLXBvaW50XG4gICAgZnVuY3Rpb24gY2F0bXVsbFJvbTJiZXppZXIoY3JwLCB6KSB7XG4gICAgICAgIHZhciBkID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpTGVuID0gY3JwLmxlbmd0aDsgaUxlbiAtIDIgKiAheiA+IGk7IGkgKz0gMikge1xuICAgICAgICAgICAgdmFyIHAgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7eDogK2NycFtpIC0gMl0sIHk6ICtjcnBbaSAtIDFdfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt4OiArY3JwW2ldLCAgICAgeTogK2NycFtpICsgMV19LFxuICAgICAgICAgICAgICAgICAgICAgICAge3g6ICtjcnBbaSArIDJdLCB5OiArY3JwW2kgKyAzXX0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7eDogK2NycFtpICsgNF0sIHk6ICtjcnBbaSArIDVdfVxuICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYgKHopIHtcbiAgICAgICAgICAgICAgICBpZiAoIWkpIHtcbiAgICAgICAgICAgICAgICAgICAgcFswXSA9IHt4OiArY3JwW2lMZW4gLSAyXSwgeTogK2NycFtpTGVuIC0gMV19O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaUxlbiAtIDQgPT0gaSkge1xuICAgICAgICAgICAgICAgICAgICBwWzNdID0ge3g6ICtjcnBbMF0sIHk6ICtjcnBbMV19O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaUxlbiAtIDIgPT0gaSkge1xuICAgICAgICAgICAgICAgICAgICBwWzJdID0ge3g6ICtjcnBbMF0sIHk6ICtjcnBbMV19O1xuICAgICAgICAgICAgICAgICAgICBwWzNdID0ge3g6ICtjcnBbMl0sIHk6ICtjcnBbM119O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGlMZW4gLSA0ID09IGkpIHtcbiAgICAgICAgICAgICAgICAgICAgcFszXSA9IHBbMl07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaSkge1xuICAgICAgICAgICAgICAgICAgICBwWzBdID0ge3g6ICtjcnBbaV0sIHk6ICtjcnBbaSArIDFdfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkLnB1c2goW1wiQ1wiLFxuICAgICAgICAgICAgICAgICAgKC1wWzBdLnggKyA2ICogcFsxXS54ICsgcFsyXS54KSAvIDYsXG4gICAgICAgICAgICAgICAgICAoLXBbMF0ueSArIDYgKiBwWzFdLnkgKyBwWzJdLnkpIC8gNixcbiAgICAgICAgICAgICAgICAgIChwWzFdLnggKyA2ICogcFsyXS54IC0gcFszXS54KSAvIDYsXG4gICAgICAgICAgICAgICAgICAocFsxXS55ICsgNipwWzJdLnkgLSBwWzNdLnkpIC8gNixcbiAgICAgICAgICAgICAgICAgIHBbMl0ueCxcbiAgICAgICAgICAgICAgICAgIHBbMl0ueVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZDtcbiAgICB9XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucGFyc2VQYXRoU3RyaW5nXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBVdGlsaXR5IG1ldGhvZFxuICAgICAqKlxuICAgICAqIFBhcnNlcyBnaXZlbiBwYXRoIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIGFycmF5cyBvZiBwYXRoIHNlZ21lbnRzLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBwYXRoU3RyaW5nIChzdHJpbmd8YXJyYXkpIHBhdGggc3RyaW5nIG9yIGFycmF5IG9mIHNlZ21lbnRzIChpbiB0aGUgbGFzdCBjYXNlIGl0IHdpbGwgYmUgcmV0dXJuZWQgc3RyYWlnaHQgYXdheSlcbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIHNlZ21lbnRzLlxuICAgIFxcKi9cbiAgICBSLnBhcnNlUGF0aFN0cmluZyA9IGZ1bmN0aW9uIChwYXRoU3RyaW5nKSB7XG4gICAgICAgIGlmICghcGF0aFN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgI
57590H1cbiAgICAgICAgdmFyIHB0aCA9IHBhdGhzKHBhdGhTdHJpbmcpO1xuICAgICAgICBpZiAocHRoLmFycikge1xuICAgICAgICAgICAgcmV0dXJuIHBhdGhDbG9uZShwdGguYXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwYXJhbUNvdW50cyA9IHthOiA3LCBjOiA2LCBoOiAxLCBsOiAyLCBtOiAyLCByOiA0LCBxOiA0LCBzOiA0LCB0OiAyLCB2OiAxLCB6OiAwfSxcbiAgICAgICAgICAgIGRhdGEgPSBbXTtcbiAgICAgICAgaWYgKFIuaXMocGF0aFN0cmluZywgYXJyYXkpICYmIFIuaXMocGF0aFN0cmluZ1swXSwgYXJyYXkpKSB7IC8vIHJvdWdoIGFzc3VtcHRpb25cbiAgICAgICAgICAgIGRhdGEgPSBwYXRoQ2xvbmUocGF0aFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgU3RyKHBhdGhTdHJpbmcpLnJlcGxhY2UocGF0aENvbW1hbmQsIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBuYW1lID0gYi50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGMucmVwbGFjZShwYXRoVmFsdWVzLCBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgICAgICBiICYmIHBhcmFtcy5wdXNoKCtiKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZSA9PSBcIm1cIiAmJiBwYXJhbXMubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgICAgICAgICBkYXRhLnB1c2goW2JdW2NvbmNhdF0ocGFyYW1zLnNwbGljZSgwLCAyKSkpO1xuICAgICAgICAgICAgICAgICAgICBuYW1lID0gXCJsXCI7XG4gICAgICAgICAgICAgICAgICAgIGIgPSBiID09IFwibVwiID8gXCJsXCIgOiBcIkxcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG5hbWUgPT0gXCJyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5wdXNoKFtiXVtjb25jYXRdKHBhcmFtcykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB3aGlsZSAocGFyYW1zLmxlbmd0aCA+PSBwYXJhbUNvdW50c1tuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhLnB1c2goW2JdW2NvbmNhdF0ocGFyYW1zLnNwbGljZSgwLCBwYXJhbUNvdW50c1tuYW1lXSkpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJhbUNvdW50c1tuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBkYXRhLnRvU3RyaW5nID0gUi5fcGF0aDJzdHJpbmc7XG4gICAgICAgIHB0aC5hcnIgPSBwYXRoQ2xvbmUoZGF0YSk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucGFyc2VUcmFuc2Zvcm1TdHJpbmdcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICoqXG4gICAgICogUGFyc2VzIGdpdmVuIHBhdGggc3RyaW5nIGludG8gYW4gYXJyYXkgb2YgdHJhbnNmb3JtYXRpb25zLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBUU3RyaW5nIChzdHJpbmd8YXJyYXkpIHRyYW5zZm9ybSBzdHJpbmcgb3IgYXJyYXkgb2YgdHJhbnNmb3JtYXRpb25zIChpbiB0aGUgbGFzdCBjYXNlIGl0IHdpbGwgYmUgcmV0dXJuZWQgc3RyYWlnaHQgYXdheSlcbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIHRyYW5zZm9ybWF0aW9ucy5cbiAgICBcXCovXG4gICAgUi5wYXJzZVRyYW5zZm9ybVN0cmluZyA9IGNhY2hlcihmdW5jdGlvbiAoVFN0cmluZykge1xuICAgICAgICBpZiAoIVRTdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJhbUNvdW50cyA9IHtyOiAzLCBzOiA0LCB0OiAyLCBtOiA2fSxcbiAgICAgICAgICAgIGRhdGEgPSBbXTtcbiAgICAgICAgaWYgKFIuaXMoVFN0cmluZywgYXJyYXkpICYmIFIuaXMoVFN0cmluZ1swXSwgYXJyYXkpKSB7IC8vIHJvdWdoIGFzc3VtcHRpb25cbiAgICAgICAgICAgIGRhdGEgPSBwYXRoQ2xvbmUoVFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgU3RyKFRTdHJpbmcpLnJlcGxhY2UodENvbW1hbmQsIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBuYW1lID0gbG93ZXJDYXNlLmNhbGwoYik7XG4gICAgICAgICAgICAgICAgYy5yZXBsYWNlKHBhdGhWYWx1ZXMsIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGIgJiYgcGFyYW1zLnB1c2goK2IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRhdGEucHVzaChbYl1bY29uY2F0XShwYXJhbXMpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEudG9TdHJpbmcgPSBSLl9wYXR
57590oMnN0cmluZztcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSwgdGhpcywgZnVuY3Rpb24oZWxlbSkge1xuICAgICAgICBpZiAoIWVsZW0pIHJldHVybiBlbGVtO1xuICAgICAgICB2YXIgbmV3RGF0YSA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBuZXdMZXZlbCA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBlbGVtW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbmV3TGV2ZWwucHVzaChlbGVtW2ldW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld0RhdGEucHVzaChuZXdMZXZlbCk7XG4gICAgICAgIH1cbiAgICAgIHJldHVybiBuZXdEYXRhOyB9ICk7XG4gICAgLy8gUEFUSFNcbiAgICB2YXIgcGF0aHMgPSBmdW5jdGlvbiAocHMpIHtcbiAgICAgICAgdmFyIHAgPSBwYXRocy5wcyA9IHBhdGhzLnBzIHx8IHt9O1xuICAgICAgICBpZiAocFtwc10pIHtcbiAgICAgICAgICAgIHBbcHNdLnNsZWVwID0gMTAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcFtwc10gPSB7XG4gICAgICAgICAgICAgICAgc2xlZXA6IDEwMFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwKSBpZiAocFtoYXNdKGtleSkgJiYga2V5ICE9IHBzKSB7XG4gICAgICAgICAgICAgICAgcFtrZXldLnNsZWVwLS07XG4gICAgICAgICAgICAgICAgIXBba2V5XS5zbGVlcCAmJiBkZWxldGUgcFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHBbcHNdO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuZmluZERvdHNBdFNlZ21lbnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICoqXG4gICAgICogRmluZCBkb3QgY29vcmRpbmF0ZXMgb24gdGhlIGdpdmVuIGN1YmljIGJlemllciBjdXJ2ZSBhdCB0aGUgZ2l2ZW4gdC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gcDF4IChudW1iZXIpIHggb2YgdGhlIGZpcnN0IHBvaW50IG9mIHRoZSBjdXJ2ZVxuICAgICAtIHAxeSAobnVtYmVyKSB5IG9mIHRoZSBmaXJzdCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgLSBjMXggKG51bWJlcikgeCBvZiB0aGUgZmlyc3QgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIGMxeSAobnVtYmVyKSB5IG9mIHRoZSBmaXJzdCBhbmNob3Igb2YgdGhlIGN1cnZlXG4gICAgIC0gYzJ4IChudW1iZXIpIHggb2YgdGhlIHNlY29uZCBhbmNob3Igb2YgdGhlIGN1cnZlXG4gICAgIC0gYzJ5IChudW1iZXIpIHkgb2YgdGhlIHNlY29uZCBhbmNob3Igb2YgdGhlIGN1cnZlXG4gICAgIC0gcDJ4IChudW1iZXIpIHggb2YgdGhlIHNlY29uZCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgLSBwMnkgKG51bWJlcikgeSBvZiB0aGUgc2Vjb25kIHBvaW50IG9mIHRoZSBjdXJ2ZVxuICAgICAtIHQgKG51bWJlcikgcG9zaXRpb24gb24gdGhlIGN1cnZlICgwLi4xKVxuICAgICA9IChvYmplY3QpIHBvaW50IGluZm9ybWF0aW9uIGluIGZvcm1hdDpcbiAgICAgbyB7XG4gICAgIG8gICAgIHg6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcbiAgICAgbyAgICAgeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICBvICAgICBtOiB7XG4gICAgIG8gICAgICAgICB4OiAobnVtYmVyKSB4IGNvb3JkaW5hdGUgb2YgdGhlIGxlZnQgYW5jaG9yXG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGxlZnQgYW5jaG9yXG4gICAgIG8gICAgIH1cbiAgICAgbyAgICAgbjoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSByaWdodCBhbmNob3JcbiAgICAgbyAgICAgICAgIHk6IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgcmlnaHQgYW5jaG9yXG4gICAgIG8gICAgIH1cbiAgICAgbyAgICAgc3RhcnQ6IHtcbiAgICAgbyAgICAgICAgIHg6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgc3RhcnQgb2YgdGhlIGN1cnZlXG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHN0YXJ0IG9mIHRoZSBjdXJ2ZVxuICAgICBvICAgICB9XG4gICAgIG8gICAgIGVuZDoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBlbmQgb2YgdGhlIGN1cnZlXG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGVuZCBvZiB0aGUgY3VydmVcbiAgICAgbyAgICAgfVxuICAgICBvICAgICBhbHBoYTogKG51bWJlcikgYW5nbGUgb2YgdGhlIGN1cnZlIGRlcml2YXRpdmUgYXQgdGhlIHBvaW50XG4gICAgIG8gfVxuICAgIFxcKi9cbiAgICBSLmZpbmREb3RzQXRTZWdtZW50ID0gZnVuY3Rpb24gKHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5LCB0KSB7XG4gICAgICAgIHZhciB0MSA9IDEgLSB0LFxuICAgICAgICAgICAgdDEzID0gcG93KHQxLCAzKSxcbiAgICAgICAgICAgIHQxMiA9IHBvdyh0MSwgMiksXG4gICAgICAgICAgICB0MiA9IHQgKiB0LFxuICAgICAgICAgICAgdDMgPSB0MiAqIHQsXG4gICAgICAgICAgICB4ID0gdDEzICogcDF4ICsgdDEyICogMyAqIHQgKiBjMXggKyB0MSAqIDMgKiB0ICogdCAqIGMyeCArIHQzICogcDJ4LFxuICAgICAgICAgICAgeSA9IHQxMyAqIHAxeSArIHQxMiAqIDMgKiB0ICogYzF5ICsgdDEgKiAzICogdCAqIHQgKiBjMnkgKyB0MyAqIHAyeSxcbiAgICAgICAgICAgIG14ID0gcDF4ICsgMiAqIHQgKiAoYzF4IC0gcDF4KSArIHQyICogKGMyeCAtIDIgKiBjMXggKyBwMXgpLFxuICAgICAgICAgICAgbXkgPSBwMXkgKyAyICogdCAqIChjMXkgLSBwMXkpICsgdDIgKiAoYzJ5IC0gMiAqIGMxeSArIHAxeSksXG4gICAgICAgICAgICBueCA9IGMxeCArIDIgKiB0ICogKGMyeCAtIGMxeCkgKyB0MiAqIChwMnggLSAyICogYzJ4ICsgYzF4KSxcbiAgICAgICAgICAgIG55ID0gYzF5ICsgMiAqIHQgKiAoYzJ5IC0gYzF5KSArIHQyICogKHAyeSAtIDIgKiBjMnkgKyBjMXkpLFxuICAgICAgICAgICAgYXggPSB0MSAqIHAxeCArIHQgKiBjMXgsXG4gICAgICAgICAgICBheSA9IHQxICogcDF5ICsgdCAqIGMxeSxcbiAgICAgICAgICAgIGN4ID0gdDEgKiBjMnggKyB0ICogcDJ4LFxuICAgICAgICAgICAgY3kgPSB0MSAqIGMyeSArIHQgKiBwMnksXG4gICAgICAgICAgICBhbHBoYSA9ICg5MCAtIG1hdGguYXRhbjIobXggLSBueCwgbXkgLSBueSkgKiAxODAgLyBQSSk7XG4gICAgICAgIChteCA+IG54IHx8IG15IDwgbnkpICYmIChhbHBoYSArPSAxODApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgI
57590Hk6IHksXG4gICAgICAgICAgICBtOiB7eDogbXgsIHk6IG15fSxcbiAgICAgICAgICAgIG46IHt4OiBueCwgeTogbnl9LFxuICAgICAgICAgICAgc3RhcnQ6IHt4OiBheCwgeTogYXl9LFxuICAgICAgICAgICAgZW5kOiB7eDogY3gsIHk6IGN5fSxcbiAgICAgICAgICAgIGFscGhhOiBhbHBoYVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuYmV6aWVyQkJveFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm4gYm91bmRpbmcgYm94IG9mIGEgZ2l2ZW4gY3ViaWMgYmV6aWVyIGN1cnZlXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHAxeCAobnVtYmVyKSB4IG9mIHRoZSBmaXJzdCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgLSBwMXkgKG51bWJlcikgeSBvZiB0aGUgZmlyc3QgcG9pbnQgb2YgdGhlIGN1cnZlXG4gICAgIC0gYzF4IChudW1iZXIpIHggb2YgdGhlIGZpcnN0IGFuY2hvciBvZiB0aGUgY3VydmVcbiAgICAgLSBjMXkgKG51bWJlcikgeSBvZiB0aGUgZmlyc3QgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIGMyeCAobnVtYmVyKSB4IG9mIHRoZSBzZWNvbmQgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIGMyeSAobnVtYmVyKSB5IG9mIHRoZSBzZWNvbmQgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIHAyeCAobnVtYmVyKSB4IG9mIHRoZSBzZWNvbmQgcG9pbnQgb2YgdGhlIGN1cnZlXG4gICAgIC0gcDJ5IChudW1iZXIpIHkgb2YgdGhlIHNlY29uZCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgKiBvclxuICAgICAtIGJleiAoYXJyYXkpIGFycmF5IG9mIHNpeCBwb2ludHMgZm9yIGJlemllciBjdXJ2ZVxuICAgICA9IChvYmplY3QpIHBvaW50IGluZm9ybWF0aW9uIGluIGZvcm1hdDpcbiAgICAgbyB7XG4gICAgIG8gICAgIG1pbjoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBsZWZ0IHBvaW50XG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHRvcCBwb2ludFxuICAgICBvICAgICB9XG4gICAgIG8gICAgIG1heDoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSByaWdodCBwb2ludFxuICAgICBvICAgICAgICAgeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBib3R0b20gcG9pbnRcbiAgICAgbyAgICAgfVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5iZXppZXJCQm94ID0gZnVuY3Rpb24gKHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5KSB7XG4gICAgICAgIGlmICghUi5pcyhwMXgsIFwiYXJyYXlcIikpIHtcbiAgICAgICAgICAgIHAxeCA9IFtwMXgsIHAxeSwgYzF4LCBjMXksIGMyeCwgYzJ5LCBwMngsIHAyeV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJib3ggPSBjdXJ2ZURpbS5hcHBseShudWxsLCBwMXgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogYmJveC5taW4ueCxcbiAgICAgICAgICAgIHk6IGJib3gubWluLnksXG4gICAgICAgICAgICB4MjogYmJveC5tYXgueCxcbiAgICAgICAgICAgIHkyOiBiYm94Lm1heC55LFxuICAgICAgICAgICAgd2lkdGg6IGJib3gubWF4LnggLSBiYm94Lm1pbi54LFxuICAgICAgICAgICAgaGVpZ2h0OiBiYm94Lm1heC55IC0gYmJveC5taW4ueVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuaXNQb2ludEluc2lkZUJCb3hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgZ2l2ZW4gcG9pbnQgaXMgaW5zaWRlIGJvdW5kaW5nIGJveGVzLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBiYm94IChzdHJpbmcpIGJvdW5kaW5nIGJveFxuICAgICAtIHggKHN0cmluZykgeCBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICAtIHkgKHN0cmluZykgeSBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICA9IChib29sZWFuKSBgdHJ1ZWAgaWYgcG9pbnQgaW5zaWRlXG4gICAgXFwqL1xuICAgIFIuaXNQb2ludEluc2lkZUJCb3ggPSBmdW5jdGlvbiAoYmJveCwgeCwgeSkge1xuICAgICAgICByZXR1cm4geCA+PSBiYm94LnggJiYgeCA8PSBiYm94LngyICYmIHkgPj0gYmJveC55ICYmIHkgPD0gYmJveC55MjtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmlzQkJveEludGVyc2VjdFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0d28gYm91bmRpbmcgYm94ZXMgaW50ZXJzZWN0XG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGJib3gxIChzdHJpbmcpIGZpcnN0IGJvdW5kaW5nIGJveFxuICAgICAtIGJib3gyIChzdHJpbmcpIHNlY29uZCBib3VuZGluZyBib3hcbiAgICAgPSAoYm9vbGVhbikgYHRydWVgIGlmIHRoZXkgaW50ZXJzZWN0XG4gICAgXFwqL1xuICAgIFIuaXNCQm94SW50ZXJzZWN0ID0gZnVuY3Rpb24gKGJib3gxLCBiYm94Mikge1xuICAgICAgICB2Y
57590XIgaSA9IFIuaXNQb2ludEluc2lkZUJCb3g7XG4gICAgICAgIHJldHVybiBpKGJib3gyLCBiYm94MS54LCBiYm94MS55KVxuICAgICAgICAgICAgfHwgaShiYm94MiwgYmJveDEueDIsIGJib3gxLnkpXG4gICAgICAgICAgICB8fCBpKGJib3gyLCBiYm94MS54LCBiYm94MS55MilcbiAgICAgICAgICAgIHx8IGkoYmJveDIsIGJib3gxLngyLCBiYm94MS55MilcbiAgICAgICAgICAgIHx8IGkoYmJveDEsIGJib3gyLngsIGJib3gyLnkpXG4gICAgICAgICAgICB8fCBpKGJib3gxLCBiYm94Mi54MiwgYmJveDIueSlcbiAgICAgICAgICAgIHx8IGkoYmJveDEsIGJib3gyLngsIGJib3gyLnkyKVxuICAgICAgICAgICAgfHwgaShiYm94MSwgYmJveDIueDIsIGJib3gyLnkyKVxuICAgICAgICAgICAgfHwgKGJib3gxLnggPCBiYm94Mi54MiAmJiBiYm94MS54ID4gYmJveDIueCB8fCBiYm94Mi54IDwgYmJveDEueDIgJiYgYmJveDIueCA+IGJib3gxLngpXG4gICAgICAgICAgICAmJiAoYmJveDEueSA8IGJib3gyLnkyICYmIGJib3gxLnkgPiBiYm94Mi55IHx8IGJib3gyLnkgPCBiYm94MS55MiAmJiBiYm94Mi55ID4gYmJveDEueSk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBiYXNlMyh0LCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICB2YXIgdDEgPSAtMyAqIHAxICsgOSAqIHAyIC0gOSAqIHAzICsgMyAqIHA0LFxuICAgICAgICAgICAgdDIgPSB0ICogdDEgKyA2ICogcDEgLSAxMiAqIHAyICsgNiAqIHAzO1xuICAgICAgICByZXR1cm4gdCAqIHQyIC0gMyAqIHAxICsgMyAqIHAyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBiZXpsZW4oeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0LCB6KSB7XG4gICAgICAgIGlmICh6ID09IG51bGwpIHtcbiAgICAgICAgICAgIHogPSAxO1xuICAgICAgICB9XG4gICAgICAgIHogPSB6ID4gMSA/IDEgOiB6IDwgMCA/IDAgOiB6O1xuICAgICAgICB2Y
57590XIgejIgPSB6IC8gMixcbiAgICAgICAgICAgIG4gPSAxMixcbiAgICAgICAgICAgIFR2YWx1ZXMgPSBbLTAuMTI1MiwwLjEyNTIsLTAuMzY3OCwwLjM2NzgsLTAuNTg3MywwLjU4NzMsLTAuNzY5OSwwLjc2OTksLTAuOTA0MSwwLjkwNDEsLTAuOTgxNiwwLjk4MTZdLFxuICAgICAgICAgICAgQ3ZhbHVlcyA9IFswLjI0OTEsMC4yNDkxLDAuMjMzNSwwLjIzMzUsMC4yMDMyLDAuMjAzMiwwLjE2MDEsMC4xNjAxLDAuMTA2OSwwLjEwNjksMC4wNDcyLDAuMDQ3Ml0sXG4gICAgICAgICAgICBzdW0gPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgdmFyIGN0ID0gejIgKiBUdmFsdWVzW2ldICsgejIsXG4gICAgICAgICAgICAgICAgeGJhc2UgPSBiYXNlMyhjdCwgeDEsIHgyLCB4MywgeDQpLFxuICAgICAgICAgICAgICAgIHliYXNlID0gYmFzZTMoY3QsIHkxLCB5MiwgeTMsIHk0KSxcbiAgICAgICAgICAgICAgICBjb21iID0geGJhc2UgKiB4YmFzZSArIHliYXNlICogeWJhc2U7XG4gICAgICAgICAgICBzdW0gKz0gQ3ZhbHVlc1tpXSAqIG1hdGguc3FydChjb21iKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gejIgKiBzdW07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGdldFRhdExlbih4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIGxsKSB7XG4gICAgICAgIGlmIChsbCA8IDAgfHwgYmV6bGVuKHgxLCB5MSwgeDIsIHkyLCB4MywgeTMsIHg0LCB5NCkgPCBsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0ID0gMSxcbiAgICAgICAgICAgIHN0ZXAgPSB0IC8gMixcbiAgICAgICAgICAgIHQyID0gdCAtIHN0ZXAsXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgZSA9IC4wMTtcbiAgICAgICAgbCA9IGJlemxlbih4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIHQyKTtcbiAgICAgICAgd2hpbGUgKGFicyhsIC0gbGwpID4gZSkge1xuICAgICAgICAgICAgc3RlcCAvPSAyO1xuICAgICAgICAgICAgdDIgKz0gKGwgPCBsbCA/IDEgOiAtMSkgKiBzdGVwO1xuICAgICAgICAgICAgbCA9IGJlemxlbih4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIHQyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGludGVyc2VjdCh4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgbW1heCh4MSwgeDIpIDwgbW1pbih4MywgeDQpIHx8XG4gICAgICAgICAgICBtbWluKHgxLCB4MikgPiBtbWF4KHgzLCB4NCkgfHxcbiAgICAgICAgICAgIG1tYXgoeTEsIHkyKSA8IG1taW4oeTMsIHk0KSB8fFxuICAgICAgICAgICAgbW1pbih5MSwgeTIpID4gbW1heCh5MywgeTQpXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBueCA9ICh4MSAqIHkyIC0geTEgKiB4MikgKiAoeDMgLSB4NCkgLSAoeDEgLSB4MikgKiAoeDMgKiB5NCAtIHkzICogeDQpLFxuICAgICAgICAgICAgbnkgPSAoeDEgKiB5MiAtIHkxICogeDIpICogKHkzIC0geTQpIC0gKHkxIC0geTIpICogKHgzICogeTQgLSB5MyAqIHg0KSxcbiAgICAgICAgICAgIGRlbm9taW5hdG9yID0gKHgxIC0geDIpICogKHkzIC0geTQpIC0gKHkxIC0geTIpICogKHgzIC0geDQpO1xuXG4gICAgICAgIGlmICghZGVub21pbmF0b3IpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgcHggPSBueCAvIGRlbm9taW5hdG9yLFxuICAgICAgICAgICAgcHkgPSBueSAvIGRlbm9taW5hdG9yLFxuICAgICAgICAgICAgcHgyID0gK3B4LnRvRml4ZWQoMiksXG4gICAgICAgICAgICBweTIgPSArcHkudG9GaXhlZCgyKTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgcHgyIDwgK21taW4oeDEsIHgyKS50b0ZpeGVkKDIpIHx8XG4gICAgICAgICAgICBweDIgPiArbW1heCh4MSwgeDIpLnRvRml4ZWQoMikgfHxcbiAgICAgICAgICAgIHB4MiA8ICttbWluKHgzLCB4NCkudG9GaXhlZCgyKSB8fFxuICAgICAgICAgICAgcHgyID4gK21tYXgoeDMsIHg0KS50b0ZpeGVkKDIpIHx8XG4gICAgICAgICAgICBweTIgPCArbW1pbih5MSwgeTIpLnRvRml4ZWQoMikgfHxcbiAgICAgICAgICAgIHB5MiA+ICttbWF4KHkxLCB5MikudG9GaXhlZCgyKSB8fFxuICAgICAgICAgICAgcHkyIDwgK21taW4oeTMsIHk0KS50b0ZpeGVkKDIpIHx8XG4gICAgICAgICAgICBweTIgPiArbW1heCh5MywgeTQpLnRvRml4ZWQoMilcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHt4OiBweCwgeTogcHl9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnRlcihiZXoxLCBiZXoyKSB7XG4gICAgICAgIHJldHVybiBpbnRlckhlbHBlcihiZXoxLCBiZXoyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gaW50ZXJDb3VudChiZXoxLCBiZXoyKSB7XG4gICAgICAgIHJldHVybiBpbnRlckhlbHBlcihiZXoxLCBiZXoyLCAxKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gaW50ZXJIZWxwZXIoYmV6MSwgYmV6MiwganVzdENvdW50KSB7XG4gICAgICAgIHZhciBiYm94MSA9IFIuYmV6aWVyQkJveChiZXoxKSxcbiAgICAgICAgICAgIGJib3gyID0gUi5iZXppZXJCQm94KGJlejIpO1xuICAgICAgICBpZiAoIVIuaXNCQm94SW50ZXJzZWN0KGJib3gxLCBiYm94MikpIHtcbiAgICAgICAgICAgIHJldHVybiBqdXN0Q291bnQgPyAwIDogW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGwxID0gYmV6bGVuLmFwcGx5KDAsIGJlejEpLFxuICAgICAgICAgICAgbDIgPSBiZXpsZW4uYXBwbHkoMCwgYmV6MiksXG4gICAgICAgICAgICBuMSA9IG1tYXgofn4obDEgLyA1KSwgMSksXG4gICAgICAgICAgICBuMiA9IG1tYXgofn4obDIgLyA1KSwgMSksXG4gICAgICAgICAgICBkb3RzMSA9IFtdLFxuICAgICAgICAgICAgZG90czIgPSBbXSxcbiAgICAgICAgICAgIHh5ID0ge30sXG4gICAgICAgICAgICByZXMgPSBqdXN0Q291bnQgPyAwIDogW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjEgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwID0gUi5maW5kRG90c0F0U2VnbWVudC5hcHBseShSLCBiZXoxLmNvbmNhdChpIC8gbjEpKTtcbiAgICAgICAgICAgIGRvdHMxLnB1c2goe3g6IHAueCwgeTogcC55LCB0OiBpIC8gbjF9KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbjIgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHAgPSBSLmZpbmREb3RzQXRTZWdtZW50LmFwcGx5KFIsIGJlejIuY29uY2F0KGkgLyBuMikpO1xuICAgICAgICAgICAgZG90czIucHVzaCh7eDogcC54LCB5OiBwLnksIHQ6IGkgLyBuMn0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBuMTsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG4yOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgZGkgPSBkb3RzMVtpXSxcbiAgICAgICAgICAgICAgICAgICAgZGkxID0gZG90czFbaSArIDFdLFxuICAgICAgICAgICAgICAgICAgICBkaiA9IGRvdHMyW2pdLFxuICAgICAgICAgICAgICAgICAgICBkajEgPSBkb3RzMltqICsgMV0sXG4gICAgICAgICAgICAgICAgICAgIGNpID0gYWJzKGRpMS54IC0gZGkueCkgPCAuMDAxID8gXCJ5XCIgOiBcInhcIixcbiAgICAgICAgICAgICAgICAgICAgY2ogPSBhYnMoZGoxLnggLSBkai54KSA8IC4wMDEgPyBcInlcIiA6IFwieFwiLFxuICAgICAgICAgICAgICAgICAgICBpcyA9IGludGVyc2VjdChkaS54LCBkaS55LCBkaTEueCwgZGkxLnksIGRqLngsIGRqLnksIGRqMS54LCBkajEueSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh4eVtpcy54LnRvRml4ZWQoNCldID09IGlzLnkudG9GaXhlZCg0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgeHlbaXMueC50b0ZpeGVkKDQpXSA9IGlzLnkudG9GaXhlZCg0KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHQxID0gZGkudCArIGFicygoaXNbY2ldIC0gZGlbY2ldKSAvIChkaTFbY2ldIC0gZGlbY2ldKSkgKiAoZGkxLnQgLSBkaS50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHQyID0gZGoudCArIGFicygoaXNbY2pdIC0gZGpbY2pdKSAvIChkajFbY2pdIC0gZGpbY2pdKSkgKiAoZGoxLnQgLSBkai50KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQxID49IDAgJiYgdDEgPD0gMS4wMDEgJiYgdDIgPj0gMCAmJiB0MiA8PSAxLjAwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGp1c3RDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg6IGlzLngsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk6IGlzLnksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQxOiBtbWluKHQxLCAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdDI6IG1taW4odDIsIDEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucGF0aEludGVyc2VjdGlvblxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBGaW5kcyBpbnRlcnNlY3Rpb25zIG9mIHR3byBwYXRoc1xuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBwYXRoMSAoc3RyaW5nKSBwYXRoIHN0cmluZ1xuICAgICAtIHBhdGgyIChzdHJpbmcpIHBhdGggc3RyaW5nXG4gICAgID0gKGFycmF5KSBkb3RzIG9mIGludGVyc2VjdGlvblxuICAgICBvIFtcbiAgICAgbyAgICAge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICBvICAgICAgICAgeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICBvICAgICAgICAgdDE6IChudW1iZXIpIHQgdmFsdWUgZm9yIHNlZ21lbnQgb2YgcGF0aDFcbiAgICAgbyAgICAgICAgIHQyOiAobnVtYmVyKSB0IHZhbHVlIGZvciBzZWdtZW50IG9mIHBhdGgyXG4gICAgIG8gICAgICAgICBzZWdtZW50MTogKG51bWJlcikgb3JkZXIgbnVtYmVyIGZvciBzZWdtZW50IG9mIHBhdGgxXG4gICAgIG8gICAgICAgICBzZWdtZW50MjogKG51bWJlcikgb3JkZXIgbnVtYmVyIGZvciBzZWdtZW50IG9mIHBhdGgyXG4gICAgIG8gICAgICAgICBiZXoxOiAoYXJyYXkpIGVpZ2h0IGNvb3JkaW5hdGVzIHJlcHJlc2VudGluZyBiZXppw6lyIGN1cnZlIGZvciB0aGUgc2VnbWVudCBvZiBwYXRoMVxuICAgICBvICAgICAgICAgYmV6MjogKGFycmF5KSBlaWdodCBjb29yZGluYXRlcyByZXByZXNlbnRpbmcgYmV6acOpciBjdXJ2ZSBmb3IgdGhlIHNlZ21lbnQgb2YgcGF0aDJcbiAgICAgbyAgICAgfVxuICAgICBvIF1cbiAgICBcXCovXG4gICAgUi5wYXRoSW50ZXJzZWN0aW9uID0gZnVuY3Rpb24gKHBhdGgxLCBwYXRoMikge1xuICAgICAgICByZXR1cm4gaW50ZXJQYXRoSGVscGVyKHBhdGgxLCBwYXRoMik7XG4gICAgfTtcbiAgICBSLnBhdGhJbnRlcnNlY3Rpb25OdW1iZXIgPSBmdW5jdGlvbiAocGF0aDEsIHBhdGgyKSB7XG4gICAgICAgIHJldHVybiBpbnRlclBhdGhIZWxwZXIocGF0aDEsIHBhdGgyLCAxKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIGludGVyUGF0aEhlbHBlcihwYXRoMSwgcGF0aDIsIGp1c3RDb3VudCkge1xuICAgICAgICBwYXRoMSA9IFIuX3BhdGgyY3VydmUocGF0aDEpO1xuICAgICAgICBwYXRoMiA9IFIuX3BhdGgyY3VydmUocGF0aDIpO1xuICAgICAgICB2Y
57590XIgeDEsIHkxLCB4MiwgeTIsIHgxbSwgeTFtLCB4Mm0sIHkybSwgYmV6MSwgYmV6MixcbiAgICAgICAgICAgIHJlcyA9IGp1c3RDb3VudCA/IDAgOiBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcGF0aDEubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgdmFyIHBpID0gcGF0aDFbaV07XG4gICAgICAgICAgICBpZiAocGlbMF0gPT0gXCJNXCIpIHtcbiAgICAgICAgICAgICAgICB4MSA9IHgxbSA9IHBpWzFdO1xuICAgICAgICAgICAgICAgIHkxID0geTFtID0gcGlbMl07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChwaVswXSA9PSBcIkNcIikge1xuICAgICAgICAgICAgICAgICAgICBiZXoxID0gW3gxLCB5MV0uY29uY2F0KHBpLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgeDEgPSBiZXoxWzZdO1xuICAgICAgICAgICAgICAgICAgICB5MSA9IGJlejFbN107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYmV6MSA9IFt4MSwgeTEsIHgxLCB5MSwgeDFtLCB5MW0sIHgxbSwgeTFtXTtcbiAgICAgICAgICAgICAgICAgICAgeDEgPSB4MW07XG4gICAgICAgICAgICAgICAgICAgIHkxID0geTFtO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMCwgamogPSBwYXRoMi5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwaiA9IHBhdGgyW2pdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGpbMF0gPT0gXCJNXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHgyID0geDJtID0gcGpbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB5MiA9IHkybSA9IHBqWzJdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBqWzBdID09IFwiQ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV6MiA9IFt4MiwgeTJdLmNvbmNhdChwai5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeDIgPSBiZXoyWzZdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gYmV6Mls3XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV6MiA9IFt4MiwgeTIsIHgyLCB5MiwgeDJtLCB5Mm0sIHgybSwgeTJtXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MiA9IHgybTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5MiA9IHkybTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnRyID0gaW50ZXJIZWxwZXIoYmV6MSwgYmV6MiwganVzdENvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChqdXN0Q291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMgKz0gaW50cjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDAsIGtrID0gaW50ci5sZW5ndGg7IGsgPCBrazsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludHJba10uc2VnbWVudDEgPSBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRyW2tdLnNlZ21lbnQyID0gajtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50cltrXS5iZXoxID0gYmV6MTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50cltrXS5iZXoyID0gYmV6MjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gcmVzLmNvbmNhdChpbnRyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5pc1BvaW50SW5zaWRlUGF0aFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiBnaXZlbiBwb2ludCBpcyBpbnNpZGUgYSBnaXZlbiBjbG9zZWQgcGF0aC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gcGF0aCAoc3RyaW5nKSBwYXRoIHN0cmluZ1xuICAgICAtIHggKG51bWJlcikgeCBvZiB0aGUgcG9pbnRcbiAgICAgLSB5IChudW1iZXIpIHkgb2YgdGhlIHBvaW50XG4gICAgID0gKGJvb2xlYW4pIHRydWUsIGlmIHBvaW50IGlzIGluc2lkZSB0aGUgcGF0aFxuICAgIFxcKi9cbiAgICBSLmlzUG9pbnRJbnNpZGVQYXRoID0gZnVuY3Rpb24gKHBhdGgsIHgsIHkpIHtcbiAgICAgICAgdmFyIGJib3ggPSBSLnBhdGhCQm94KHBhdGgpO1xuICAgICAgICByZXR1cm4gUi5pc1BvaW50SW5zaWRlQkJveChiYm94LCB4LCB5KSAmJlxuICAgICAgICAgICAgICAgaW50ZXJQYXRoSGVscGVyKHBhdGgsIFtbXCJNXCIsIHgsIHldLCBbXCJIXCIsIGJib3gueDIgKyAxMF1dLCAxKSAlIDIgPT0gMTtcbiAgICB9O1xuICAgIFIuX3JlbW92ZWRGYWN0b3J5ID0gZnVuY3Rpb24gKG1ldGhvZG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV2ZShcInJhcGhhZWwubG9nXCIsIG51bGwsIFwiUmFwaGFcXHhlYmw6IHlvdSBhcmUgY2FsbGluZyB0byBtZXRob2QgXFx1MjAxY1wiICsgbWV0aG9kbmFtZSArIFwiXFx1MjAxZCBvZiByZW1vdmVkIG9iamVjdFwiLCBtZXRob2RuYW1lKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnBhdGhCQm94XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBVdGlsaXR5IG1ldGhvZFxuICAgICAqKlxuICAgICAqIFJldHVybiBib3VuZGluZyBib3ggb2YgYSBnaXZlbiBwYXRoXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHBhdGggKHN0cmluZykgcGF0aCBzdHJpbmdcbiAgICAgPSAob2JqZWN0KSBib3VuZGluZyBib3hcbiAgICAgbyB7XG4gICAgIG8gICAgIHg6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgbGVmdCB0b3AgcG9pbnQgb2YgdGhlIGJveFxuICAgICBvICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGxlZnQgdG9wIHBvaW50IG9mIHRoZSBib3hcbiAgICAgbyAgICAgeDI6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgcmlnaHQgYm90dG9tIHBvaW50IG9mIHRoZSBib3hcbiAgICAgbyAgICAgeTI6IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgcmlnaHQgYm90dG9tIHBvaW50IG9mIHRoZSBib3hcbiAgICAgbyAgICAgd2lkdGg6IChudW1iZXIpIHdpZHRoIG9mIHRoZSBib3hcbiAgICAgbyAgICAgaGVpZ2h0OiAobnVtYmVyKSBoZWlnaHQgb2YgdGhlIGJveFxuICAgICBvICAgICBjeDogKG51bWJlcikgeCBjb29yZGluYX
57590RlIG9mIHRoZSBjZW50ZXIgb2YgdGhlIGJveFxuICAgICBvICAgICBjeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBjZW50ZXIgb2YgdGhlIGJveFxuICAgICBvIH1cbiAgICBcXCovXG4gICAgdmFyIHBhdGhEaW1lbnNpb25zID0gUi5wYXRoQkJveCA9IGZ1bmN0aW9uIChwYXRoKSB7XG4gICAgICAgIHZhciBwdGggPSBwYXRocyhwYXRoKTtcbiAgICAgICAgaWYgKHB0aC5iYm94KSB7XG4gICAgICAgICAgICByZXR1cm4gY2xvbmUocHRoLmJib3gpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHt4OiAwLCB5OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwLCB4MjogMCwgeTI6IDB9O1xuICAgICAgICB9XG4gICAgICAgIHBhdGggPSBwYXRoMmN1cnZlKHBhdGgpO1xuICAgICAgICB2YXIgeCA9IDAsXG4gICAgICAgICAgICB5ID0gMCxcbiAgICAgICAgICAgIFggPSBbXSxcbiAgICAgICAgICAgIFkgPSBbXSxcbiAgICAgICAgICAgIHA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHBhdGgubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgcCA9IHBhdGhbaV07XG4gICAgICAgICAgICBpZiAocFswXSA9PSBcIk1cIikge1xuICAgICAgICAgICAgICAgIHggPSBwWzFdO1xuICAgICAgICAgICAgICAgIHkgPSBwWzJdO1xuICAgICAgICAgICAgICAgIFgucHVzaCh4KTtcbiAgICAgICAgICAgICAgICBZLnB1c2goeSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkaW0gPSBjdXJ2ZURpbSh4LCB5LCBwWzFdLCBwWzJdLCBwWzNdLCBwWzRdLCBwWzVdLCBwWzZdKTtcbiAgICAgICAgICAgICAgICBYID0gWFtjb25jYXRdKGRpbS5taW4ueCwgZGltLm1heC54KTtcbiAgICAgICAgICAgICAgICBZID0gWVtjb25jYXRdKGRpbS5taW4ueSwgZGltLm1heC55KTtcbiAgICAgICAgICAgICAgICB4ID0gcFs1XTtcbiAgICAgICAgICAgICAgICB5ID0gcFs2XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgeG1pbiA9IG1taW5bYXBwbHldKDAsIFgpLFxuICAgICAgICAgICAgeW1pbiA9IG1taW5bYXBwbHldKDAsIFkpLFxuICAgICAgICAgICAgeG1heCA9IG1tYXhbYXBwbHldKDAsIFgpLFxuICAgICAgICAgICAgeW1heCA9IG1tYXhbYXBwbHldKDAsIFkpLFxuICAgICAgICAgICAgd2lkdGggPSB4bWF4IC0geG1pbixcbiAgICAgICAgICAgIGhlaWdodCA9IHltYXggLSB5bWluLFxuICAgICAgICAgICAgICAgIGJiID0ge1xuICAgICAgICAgICAgICAgIHg6IHhtaW4sXG4gICAgICAgICAgICAgICAgeTogeW1pbixcbiAgICAgICAgICAgICAgICB4MjogeG1heCxcbiAgICAgICAgICAgICAgICB5MjogeW1heCxcbiAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICAgICAgY3g6IHhtaW4gKyB3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgY3k6IHltaW4gKyBoZWlnaHQgLyAyXG4gICAgICAgICAgICB9O1xuICAgICAgICBwdGguYmJveCA9IGNsb25lKGJiKTtcbiAgICAgICAgcmV0dXJuIGJiO1xuICAgIH0sXG4gICAgICAgIHBhdGhDbG9uZSA9IGZ1bmN0aW9uIChwYXRoQXJyYXkpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSBjbG9uZShwYXRoQXJyYXkpO1xuICAgICAgICAgICAgcmVzLnRvU3RyaW5nID0gUi5fcGF0aDJzdHJpbmc7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9LFxuICAgICAgICBwYXRoVG9SZWxhdGl2ZSA9IFIuX3BhdGhUb1JlbGF0aXZlID0gZnVuY3Rpb24gKHBhdGhBcnJheSkge1xuICAgICAgICAgICAgdmFyIHB0aCA9IHBhdGhzKHBhdGhBcnJheSk7XG4gICAgICAgICAgICBpZiAocHRoLnJlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRoQ2xvbmUocHRoLnJlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIVIuaXMocGF0aEFycmF5LCBhcnJheSkgfHwgIVIuaXMocGF0aEFycmF5ICYmIHBhdGhBcnJheVswXSwgYXJyYXkpKSB7IC8vIHJvdWdoIGFzc3VtcHRpb25cbiAgICAgICAgICAgICAgICBwYXRoQXJyYXkgPSBSLnBhcnNlUGF0aFN0cmluZyhwYXRoQXJyYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlcyA9IFtdLFxuICAgICAgICAgICAgICAgIHggPSAwLFxuICAgICAgICAgICAgICAgIHkgPSAwLFxuICAgICAgICAgICAgICAgIG14ID0gMCxcbiAgICAgICAgICAgICAgICBteSA9IDAsXG4gICAgICAgICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICAgICAgaWYgKHBhdGhBcnJheVswXVswXSA9PSBcIk1cIikge1xuICAgICAgICAgICAgICAgIHggPSBwYXRoQXJyYXlbMF1bMV07XG4gICAgICAgICAgICAgICAgeSA9IHBhdGhBcnJheVswXVsyXTtcbiAgICAgICAgICAgICAgICBteCA9IHg7XG4gICAgICAgICAgICAgICAgbXkgPSB5O1xuICAgICAgICAgICAgICAgIHN0YXJ0Kys7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goW1wiTVwiLCB4LCB5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gc3RhcnQsIGlpID0gcGF0aEFycmF5Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgciA9IHJlc1tpXSA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBwYSA9IHBhdGhBcnJheVtpXTtcbiAgICAgICAgICAgICAgICBpZiAocGFbMF0gIT0gbG93ZXJDYXNlLmNhbGwocGFbMF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJbMF0gPSBsb3dlckNhc2UuY2FsbChwYVswXSk7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoclswXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzFdID0gcGFbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgclsyXSA9IHBhWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbM10gPSBwYVszXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzRdID0gcGFbNF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcls1XSA9IHBhWzVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbNl0gPSArKHBhWzZdIC0geCkudG9GaXhlZCgzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzddID0gKyhwYVs3XSAtIHkpLnRvRml4ZWQoMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwidlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbMV0gPSArKHBhWzFdIC0geSkudG9GaXhlZCgzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJtXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSBwYVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBteSA9IHBhWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMSwgamogPSBwYS5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbal0gPSArKHBhW2pdIC0gKChqICUgMikgPyB4IDogeSkpLnRvRml4ZWQoMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgciA9IHJlc1tpXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFbMF0gPT0gXCJtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG14ID0gcGFbMV0gKyB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgbXkgPSBwYVsyXSArIHk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDAsIGtrID0gcGEubGVuZ3RoOyBrIDwga2s7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzW2ldW2tdID0gcGFba107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IHJlc1tpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChyZXNbaV1bMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInpcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBteDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBteTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgeCArPSArcmVzW2ldW2xlbiAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ2XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB5ICs9ICtyZXNbaV1bbGVuIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggKz0gK3Jlc1tpXVtsZW4gLSAyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHkgKz0gK3Jlc1tpXVtsZW4gLSAxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMudG9TdHJpbmcgPSBSLl9wYXR
57590oMnN0cmluZztcbiAgICAgICAgICAgIHB0aC5yZWwgPSBwYXRoQ2xvbmUocmVzKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0sXG4gICAgICAgIHBhdGhUb0Fic29sdXRlID0gUi5fcGF0aFRvQWJzb2x1dGUgPSBmdW5jdGlvbiAocGF0aEFycmF5KSB7XG4gICAgICAgICAgICB2YXIgcHRoID0gcGF0aHMocGF0aEFycmF5KTtcbiAgICAgICAgICAgIGlmIChwdGguYWJzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGhDbG9uZShwdGguYWJzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghUi5pcyhwYXRoQXJyYXksIGFycmF5KSB8fCAhUi5pcyhwYXRoQXJyYXkgJiYgcGF0aEFycmF5WzBdLCBhcnJheSkpIHsgLy8gcm91Z2ggYXNzdW1wdGlvblxuICAgICAgICAgICAgICAgIHBhdGhBcnJheSA9IFIucGFyc2VQYXRoU3RyaW5nKHBhdGhBcnJheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBhdGhBcnJheSB8fCAhcGF0aEFycmF5Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbW1wiTVwiLCAwLCAwXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmVzID0gW10sXG4gICAgICAgICAgICAgICAgeCA9IDAsXG4gICAgICAgICAgICAgICAgeSA9IDAsXG4gICAgICAgICAgICAgICAgbXggPSAwLFxuICAgICAgICAgICAgICAgIG15ID0gMCxcbiAgICAgICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgICAgICBpZiAocGF0aEFycmF5WzBdWzBdID09IFwiTVwiKSB7XG4gICAgICAgICAgICAgICAgeCA9ICtwYXRoQXJyYXlbMF1bMV07XG4gICAgICAgICAgICAgICAgeSA9ICtwYXRoQXJyYXlbMF1bMl07XG4gICAgICAgICAgICAgICAgbXggPSB4O1xuICAgICAgICAgICAgICAgIG15ID0geTtcbiAgICAgICAgICAgICAgICBzdGFydCsrO1xuICAgICAgICAgICAgICAgIHJlc1swXSA9IFtcIk1cIiwgeCwgeV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2Y
57590XIgY3J6ID0gcGF0aEFycmF5Lmxlbmd0aCA9PSAzICYmIHBhdGhBcnJheVswXVswXSA9PSBcIk1cIiAmJiBwYXRoQXJyYXlbMV1bMF0udG9VcHBlckNhc2UoKSA9PSBcIlJcIiAmJiBwYXRoQXJyYXlbMl1bMF0udG9VcHBlckNhc2UoKSA9PSBcIlpcIjtcbiAgICAgICAgICAgIGZvciAodmFyIHIsIHBhLCBpID0gc3RhcnQsIGlpID0gcGF0aEFycmF5Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChyID0gW10pO1xuICAgICAgICAgICAgICAgIHBhID0gcGF0aEFycmF5W2ldO1xuICAgICAgICAgICAgICAgIGlmIChwYVswXSAhPSB1cHBlckNhc2UuY2FsbChwYVswXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgclswXSA9IHVwcGVyQ2FzZS5jYWxsKHBhWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiQVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbMV0gPSBwYVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzJdID0gcGFbMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgclszXSA9IHBhWzNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbNF0gPSBwYVs0XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzVdID0gcGFbNV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcls2XSA9ICsocGFbNl0gKyB4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzddID0gKyhwYVs3XSArIHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlZcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzFdID0gK3BhWzFdICsgeTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJIXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgclsxXSA9ICtwYVsxXSArIHg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiUlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkb3RzID0gW3gsIHldW2NvbmNhdF0ocGEuc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAyLCBqaiA9IGRvdHMubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3RzW2pdID0gK2RvdHNbal0gKyB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3RzWysral0gPSArZG90c1tqXSArIHk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMgPSByZXNbY29uY2F0XShjYXRtdWxsUm9tMmJlemllcihkb3RzLCBjcnopKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJNXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSArcGFbMV0gKyB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG15ID0gK3BhWzJdICsgeTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMSwgamogPSBwYS5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbal0gPSArcGFbal0gKyAoKGogJSAyKSA/IHggOiB5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhWzBdID09IFwiUlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvdHMgPSBbeCwgeV1bY29uY2F0XShwYS5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzID0gcmVzW2NvbmNhdF0oY2F0bXVsbFJvbTJiZXppZXIoZG90cywgY3J6KSk7XG4gICAgICAgICAgICAgICAgICAgIHIgPSBbXCJSXCJdW2NvbmNhdF0ocGEuc2xpY2UoLTIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMCwga2sgPSBwYS5sZW5ndGg7IGsgPCBrazsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByW2tdID0gcGFba107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3dpdGNoIChyWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJaXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB4ID0gbXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB5ID0gbXk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkhcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSByWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJWXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB5ID0gclsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiTVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgbXggPSByW3IubGVuZ3RoIC0gMl07XG4gICAgICAgICAgICAgICAgICAgICAgICBteSA9IHJbci5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSByW3IubGVuZ3RoIC0gMl07XG4gICAgICAgICAgICAgICAgICAgICAgICB5ID0gcltyLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcy50b1N0cmluZyA9IFIuX3BhdGgyc3RyaW5nO1xuICAgICAgICAgICAgcHRoLmFicyA9IHBhdGhDbG9uZShyZXMpO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSxcbiAgICAgICAgbDJjID0gZnVuY3Rpb24gKHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgICAgICByZXR1cm4gW3gxLCB5MSwgeDIsIHkyLCB4MiwgeTJdO1xuICAgICAgICB9LFxuICAgICAgICBxMmMgPSBmdW5jdGlvbiAoeDEsIHkxLCBheCwgYXksIHgyLCB5Mikge1xuICAgICAgICAgICAgdmFyIF8xMyA9IDEgLyAzLFxuICAgICAgICAgICAgICAgIF8yMyA9IDIgLyAzO1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeDEgKyBfMjMgKiBheCxcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeTEgKyBfMjMgKiBheSxcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeDIgKyBfMjMgKiBheCxcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeTIgKyBfMjMgKiBheSxcbiAgICAgICAgICAgICAgICAgICAgeDIsXG4gICAgICAgICAgICAgICAgICAgI
57590HkyXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgfSxcbiAgICAgICAgYTJjID0gZnVuY3Rpb24gKHgxLCB5MSwgcngsIHJ5LCBhbmdsZSwgbGFyZ2VfYXJjX2ZsYWcsIHN3ZWVwX2ZsYWcsIHgyLCB5MiwgcmVjdXJzaXZlKSB7XG4gICAgICAgICAgICAvLyBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvZiB3aGVyZSB0aGlzIG1hdGggY2FtZSBmcm9tIHZpc2l0OlxuICAgICAgICAgICAgLy8gaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvaW1wbG5vdGUuaHRtbCNBcmNJbXBsZW1lbnRhdGlvbk5vdGVzXG4gICAgICAgICAgICB2YXIgXzEyMCA9IFBJICogMTIwIC8gMTgwLFxuICAgICAgICAgICAgICAgIHJhZCA9IFBJIC8gMTgwICogKCthbmdsZSB8fCAwKSxcbiAgICAgICAgICAgICAgICByZXMgPSBbXSxcbiAgICAgICAgICAgICAgICB4eSxcbiAgICAgICAgICAgICAgICByb3RhdGUgPSBjYWNoZXIoZnVuY3Rpb24gKHgsIHksIHJhZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgWCA9IHggKiBtYXRoLmNvcyhyYWQpIC0geSAqIG1hdGguc2luKHJhZCksXG4gICAgICAgICAgICAgICAgICAgICAgICBZID0geCAqIG1hdGguc2luKHJhZCkgKyB5ICogbWF0aC5jb3MocmFkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt4OiBYLCB5OiBZfTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghcmVjdXJzaXZlKSB7XG4gICAgICAgICAgICAgICAgeHkgPSByb3RhdGUoeDEsIHkxLCAtcmFkKTtcbiAgICAgICAgICAgICAgICB4MSA9IHh5Lng7XG4gICAgICAgICAgICAgICAgeTEgPSB4eS55O1xuICAgICAgICAgICAgICAgIHh5ID0gcm90YXRlKHgyLCB5MiwgLXJhZCk7XG4gICAgICAgICAgICAgICAgeDIgPSB4eS54O1xuICAgICAgICAgICAgICAgIHkyID0geHkueTtcbiAgICAgICAgICAgICAgICB2Y
57590XIgY29zID0gbWF0aC5jb3MoUEkgLyAxODAgKiBhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIHNpbiA9IG1hdGguc2luKFBJIC8gMTgwICogYW5nbGUpLFxuICAgICAgICAgICAgICAgICAgICB4ID0gKHgxIC0geDIpIC8gMixcbiAgICAgICAgICAgICAgICAgICAgeSA9ICh5MSAtIHkyKSAvIDI7XG4gICAgICAgICAgICAgICAgdmFyIGggPSAoeCAqIHgpIC8gKHJ4ICogcngpICsgKHkgKiB5KSAvIChyeSAqIHJ5KTtcbiAgICAgICAgICAgICAgICBpZiAoaCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaCA9IG1hdGguc3FydChoKTtcbiAgICAgICAgICAgICAgICAgICAgcnggPSBoICogcng7XG4gICAgICAgICAgICAgICAgICAgIHJ5ID0gaCAqIHJ5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcngyID0gcnggKiByeCxcbiAgICAgICAgICAgICAgICAgICAgcnkyID0gcnkgKiByeSxcbiAgICAgICAgICAgICAgICAgICAgayA9IChsYXJnZV9hcmNfZmxhZyA9PSBzd2VlcF9mbGFnID8gLTEgOiAxKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRoLnNxcnQoYWJzKChyeDIgKiByeTIgLSByeDIgKiB5ICogeSAtIHJ5MiAqIHggKiB4KSAvIChyeDIgKiB5ICogeSArIHJ5MiAqIHggKiB4KSkpLFxuICAgICAgICAgICAgICAgICAgICBjeCA9IGsgKiByeCAqIHkgLyByeSArICh4MSArIHgyKSAvIDIsXG4gICAgICAgICAgICAgICAgICAgIGN5ID0gayAqIC1yeSAqIHggLyByeCArICh5MSArIHkyKSAvIDIsXG4gICAgICAgICAgICAgICAgICAgIGYxID0gbWF0aC5hc2luKCgoeTEgLSBjeSkgLyByeSkudG9GaXhlZCg5KSksXG4gICAgICAgICAgICAgICAgICAgIGYyID0gbWF0aC5hc2luKCgoeTIgLSBjeSkgLyByeSkudG9GaXhlZCg5KSk7XG5cbiAgICAgICAgICAgICAgICBmMSA9IHgxIDwgY3ggPyBQSSAtIGYxIDogZjE7XG4gICAgICAgICAgICAgICAgZjIgPSB4MiA8IGN4ID8gUEkgLSBmMiA6IGYyO1xuICAgICAgICAgICAgICAgIGYxIDwgMCAmJiAoZjEgPSBQSSAqIDIgKyBmMSk7XG4gICAgICAgICAgICAgICAgZjIgPCAwICYmIChmMiA9IFBJICogMiArIGYyKTtcbiAgICAgICAgICAgICAgICBpZiAoc3dlZXBfZmxhZyAmJiBmMSA+IGYyKSB7XG4gICAgICAgICAgICAgICAgICAgIGYxID0gZjEgLSBQSSAqIDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghc3dlZXBfZmxhZyAmJiBmMiA+IGYxKSB7XG4gICAgICAgICAgICAgICAgICAgIGYyID0gZjIgLSBQSSAqIDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmMSA9IHJlY3Vyc2l2ZVswXTtcbiAgICAgICAgICAgICAgICBmMiA9IHJlY3Vyc2l2ZVsxXTtcbiAgICAgICAgICAgICAgICBjeCA9IHJlY3Vyc2l2ZVsyXTtcbiAgICAgICAgICAgICAgICBjeSA9IHJlY3Vyc2l2ZVszXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkZiA9IGYyIC0gZjE7XG4gICAgICAgICAgICBpZiAoYWJzKGRmKSA+IF8xMjApIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgZjJvbGQgPSBmMixcbiAgICAgICAgICAgICAgICAgICAgeDJvbGQgPSB4MixcbiAgICAgICAgICAgICAgICAgICAgeTJvbGQgPSB5MjtcbiAgICAgICAgICAgICAgICBmMiA9IGYxICsgXzEyMCAqIChzd2VlcF9mbGFnICYmIGYyID4gZjEgPyAxIDogLTEpO1xuICAgICAgICAgICAgICAgIHgyID0gY3ggKyByeCAqIG1hdGguY29zKGYyKTtcbiAgICAgICAgICAgICAgICB5MiA9IGN5ICsgcnkgKiBtYXRoLnNpbihmMik7XG4gICAgICAgICAgICAgICAgcmVzID0gYTJjKHgyLCB5MiwgcngsIHJ5LCBhbmdsZSwgMCwgc3dlZXBfZmxhZywgeDJvbGQsIHkyb2xkLCBbZjIsIGYyb2xkLCBjeCwgY3ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRmID0gZjIgLSBmMTtcbiAgICAgICAgICAgIHZhciBjMSA9IG1hdGguY29zKGYxKSxcbiAgICAgICAgICAgICAgICBzMSA9IG1hdGguc2luKGYxKSxcbiAgICAgICAgICAgICAgICBjMiA9IG1hdGguY29zKGYyKSxcbiAgICAgICAgICAgICAgICBzMiA9IG1hdGguc2luKGYyKSxcbiAgICAgICAgICAgICAgICB0ID0gbWF0aC50YW4oZGYgLyA0KSxcbiAgICAgICAgICAgICAgICBoeCA9IDQgLyAzICogcnggKiB0LFxuICAgICAgICAgICAgICAgIGh5ID0gNCAvIDMgKiByeSAqIHQsXG4gICAgICAgICAgICAgICAgbTEgPSBbeDEsIHkxXSxcbiAgICAgICAgICAgICAgICBtMiA9IFt4MSArIGh4ICogczEsIHkxIC0gaHkgKiBjMV0sXG4gICAgICAgICAgICAgICAgbTMgPSBbeDIgKyBoeCAqIHMyLCB5MiAtIGh5ICogYzJdLFxuICAgICAgICAgICAgICAgIG00ID0gW3gyLCB5Ml07XG4gICAgICAgICAgICBtMlswXSA9IDIgKiBtMVswXSAtIG0yWzBdO1xuICAgICAgICAgICAgbTJbMV0gPSAyICogbTFbMV0gLSBtMlsxXTtcbiAgICAgICAgICAgIGlmIChyZWN1cnNpdmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW20yLCBtMywgbTRdW2NvbmNhdF0ocmVzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzID0gW20yLCBtMywgbTRdW2NvbmNhdF0ocmVzKS5qb2luKClbc3BsaXRdKFwiLFwiKTtcbiAgICAgICAgICAgICAgICB2Y
57590XIgbmV3cmVzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3cmVzW2ldID0gaSAlIDIgPyByb3RhdGUocmVzW2kgLSAxXSwgcmVzW2ldLCByYWQpLnkgOiByb3RhdGUocmVzW2ldLCByZXNbaSArIDFdLCByYWQpLng7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdyZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGZpbmREb3RBdFNlZ21lbnQgPSBmdW5jdGlvbiAocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIHQpIHtcbiAgICAgICAgICAgIHZhciB0MSA9IDEgLSB0O1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiBwb3codDEsIDMpICogcDF4ICsgcG93KHQxLCAyKSAqIDMgKiB0ICogYzF4ICsgdDEgKiAzICogdCAqIHQgKiBjMnggKyBwb3codCwgMykgKiBwMngsXG4gICAgICAgICAgICAgICAgeTogcG93KHQxLCAzKSAqIHAxeSArIHBvdyh0MSwgMikgKiAzICogdCAqIGMxeSArIHQxICogMyAqIHQgKiB0ICogYzJ5ICsgcG93KHQsIDMpICogcDJ5XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICBjdXJ2ZURpbSA9IGNhY2hlcihmdW5jdGlvbiAocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnkpIHtcbiAgICAgICAgICAgIHZhciBhID0gKGMyeCAtIDIgKiBjMXggKyBwMXgpIC0gKHAyeCAtIDIgKiBjMnggKyBjMXgpLFxuICAgICAgICAgICAgICAgIGIgPSAyICogKGMxeCAtIHAxeCkgLSAyICogKGMyeCAtIGMxeCksXG4gICAgICAgICAgICAgICAgYyA9IHAxeCAtIGMxeCxcbiAgICAgICAgICAgICAgICB0MSA9ICgtYiArIG1hdGguc3FydChiICogYiAtIDQgKiBhICogYykpIC8gMiAvIGEsXG4gICAgICAgICAgICAgICAgdDIgPSAoLWIgLSBtYXRoLnNxcnQoYiAqIGIgLSA0ICogYSAqIGMpKSAvIDIgLyBhLFxuICAgICAgICAgICAgICAgIHkgPSBbcDF5LCBwMnldLFxuICAgICAgICAgICAgICAgIHggPSBbcDF4LCBwMnhdLFxuICAgICAgICAgICAgICAgIGRvdDtcbiAgICAgICAgICAgIGFicyh0MSkgPiBcIjFlMTJcIiAmJiAodDEgPSAuNSk7XG4gICAgICAgICAgICBhYnModDIpID4gXCIxZTEyXCIgJiYgKHQyID0gLjUpO1xuICAgICAgICAgICAgaWYgKHQxID4gMCAmJiB0MSA8IDEpIHtcbiAgICAgICAgICAgICAgICBkb3QgPSBmaW5kRG90QXRTZWdtZW50KHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5LCB0MSk7XG4gICAgICAgICAgICAgICAgeC5wdXNoKGRvdC54KTtcbiAgICAgICAgICAgICAgICB5LnB1c2goZG90LnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHQyID4gMCAmJiB0MiA8IDEpIHtcbiAgICAgICAgICAgICAgICBkb3QgPSBmaW5kRG90QXRTZWdtZW50KHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5LCB0Mik7XG4gICAgICAgICAgICAgICAgeC5wdXNoKGRvdC54KTtcbiAgICAgICAgICAgICAgICB5LnB1c2goZG90LnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYSA9IChjMnkgLSAyICogYzF5ICsgcDF5KSAtIChwMnkgLSAyICogYzJ5ICsgYzF5KTtcbiAgICAgICAgICAgIGIgPSAyICogKGMxeSAtIHAxeSkgLSAyICogKGMyeSAtIGMxeSk7XG4gICAgICAgICAgICBjID0gcDF5IC0gYzF5O1xuICAgICAgICAgICAgdDEgPSAoLWIgKyBtYXRoLnNxcnQoYiAqIGIgLSA0ICogYSAqIGMpKSAvIDIgLyBhO1xuICAgICAgICAgICAgdDIgPSAoLWIgLSBtYXRoLnNxcnQoYiAqIGIgLSA0ICogYSAqIGMpKSAvIDIgLyBhO1xuICAgICAgICAgICAgYWJzKHQxKSA+IFwiMWUxMlwiICYmICh0MSA9IC41KTtcbiAgICAgICAgICAgIGFicyh0MikgPiBcIjFlMTJcIiAmJiAodDIgPSAuNSk7XG4gICAgICAgICAgICBpZiAodDEgPiAwICYmIHQxIDwgMSkge1xuICAgICAgICAgICAgICAgIGRvdCA9IGZpbmREb3RBdFNlZ21lbnQocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIHQxKTtcbiAgICAgICAgICAgICAgICB4LnB1c2goZG90LngpO1xuICAgICAgICAgICAgICAgIHkucHVzaChkb3QueSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodDIgPiAwICYmIHQyIDwgMSkge1xuICAgICAgICAgICAgICAgIGRvdCA9IGZpbmREb3RBdFNlZ21lbnQocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIHQyKTtcbiAgICAgICAgICAgICAgICB4LnB1c2goZG90LngpO1xuICAgICAgICAgICAgICAgIHkucHVzaChkb3QueSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1pbjoge3g6IG1taW5bYXBwbHldKDAsIHgpLCB5OiBtbWluW2FwcGx5XSgwLCB5KX0sXG4gICAgICAgICAgICAgICAgbWF4OiB7eDogbW1heFthcHBseV0oMCwgeCksIHk6IG1tYXhbYXBwbHldKDAsIHkpfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICAgIHBhdGgyY3VydmUgPSBSLl9wYXR
57590oMmN1cnZlID0gY2FjaGVyKGZ1bmN0aW9uIChwYXRoLCBwYXRoMikge1xuICAgICAgICAgICAgdmFyIHB0aCA9ICFwYXRoMiAmJiBwYXRocyhwYXRoKTtcbiAgICAgICAgICAgIGlmICghcGF0aDIgJiYgcHRoLmN1cnZlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGhDbG9uZShwdGguY3VydmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHAgPSBwYXRoVG9BYnNvbHV0ZShwYXRoKSxcbiAgICAgICAgICAgICAgICBwMiA9IHBhdGgyICYmIHBhdGhUb0Fic29sdXRlKHBhdGgyKSxcbiAgICAgICAgICAgICAgICBhdHRycyA9IHt4OiAwLCB5OiAwLCBieDogMCwgYnk6IDAsIFg6IDAsIFk6IDAsIHF4OiBudWxsLCBxeTogbnVsbH0sXG4gICAgICAgICAgICAgICAgYXR0cnMyID0ge3g6IDAsIHk6IDAsIGJ4OiAwLCBieTogMCwgWDogMCwgWTogMCwgcXg6IG51bGwsIHF5OiBudWxsfSxcbiAgICAgICAgICAgICAgICBwcm9jZXNzUGF0aCA9IGZ1bmN0aW9uIChwYXRoLCBkLCBwY29tKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBueCwgbnksIHRxID0ge1Q6MSwgUToxfTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW1wiQ1wiLCBkLngsIGQueSwgZC54LCBkLnksIGQueCwgZC55XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAhKHBhdGhbMF0gaW4gdHEpICYmIChkLnF4ID0gZC5xeSA9IG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHBhdGhbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJNXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZC5YID0gcGF0aFsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLlkgPSBwYXRoWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKGEyY1thcHBseV0oMCwgW2QueCwgZC55XVtjb25jYXRdKHBhdGguc2xpY2UoMSkpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiU1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwY29tID09IFwiQ1wiIHx8IHBjb20gPT0gXCJTXCIpIHsgLy8gSW4gXCJTXCIgY2FzZSB3ZSBoYXZlIHRvIHRha2UgaW50byBhY2NvdW50LCBpZiB0aGUgcHJldmlvdXMgY29tbWFuZCBpcyBDL1MuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG54ID0gZC54ICogMiAtIGQuYng7ICAgICAgICAgIC8vIEFuZCByZWZsZWN0IHRoZSBwcmV2aW91c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBueSA9IGQueSAqIDIgLSBkLmJ5OyAgICAgICAgICAvLyBjb21tYW5kJ3MgY29udHJvbCBwb2ludCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBwb2ludC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9yIHNvbWUgZWxzZSBvciBub3RoaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG54ID0gZC54O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBueSA9IGQueTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IFtcIkNcIiwgbngsIG55XVtjb25jYXRdKHBhdGguc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGNvbSA9PSBcIlFcIiB8fCBwY29tID09IFwiVFwiKSB7IC8vIEluIFwiVFwiIGNhc2Ugd2UgaGF2ZSB0byB0YWtlIGludG8gYWNjb3VudCwgaWYgdGhlIHByZXZpb3VzIGNvbW1hbmQgaXMgUS9ULlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF4ID0gZC54ICogMiAtIGQucXg7ICAgICAgICAvLyBBbmQgbWFrZSBhIHJlZmxlY3Rpb24gc2ltaWxhclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF5ID0gZC55ICogMiAtIGQucXk7ICAgICAgICAvLyB0byBjYXNlIFwiU1wiLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3Igc29tZXRoaW5nIGVsc2Ugb3Igbm90aGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF4ID0gZC54O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF5ID0gZC55O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKHEyYyhkLngsIGQueSwgZC5xeCwgZC5xeSwgcGF0aFsxXSwgcGF0aFsyXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF4ID0gcGF0aFsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF5ID0gcGF0aFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKHEyYyhkLngsIGQueSwgcGF0aFsxXSwgcGF0aFsyXSwgcGF0aFszXSwgcGF0aFs0XSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkxcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKGwyYyhkLngsIGQueSwgcGF0aFsxXSwgcGF0aFsyXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkhcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKGwyYyhkLngsIGQueSwgcGF0aFsxXSwgZC55KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiVlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgI
57590HBhdGggPSBbXCJDXCJdW2NvbmNhdF0obDJjKGQueCwgZC55LCBkLngsIHBhdGhbMV0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJaXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IFtcIkNcIl1bY29uY2F0XShsMmMoZC54LCBkLnksIGQuWCwgZC5ZKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmaXhBcmMgPSBmdW5jdGlvbiAocHAsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBwW2ldLmxlbmd0aCA+IDcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBwW2ldLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGkgPSBwcFtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChwaS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwY29tczFbaV09XCJBXCI7IC8vIGlmIGNyZWF0ZWQgbXVsdGlwbGUgQzpzLCB0aGVpciBvcmlnaW5hbCBzZWcgaXMgc2F2ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwMiAmJiAocGNvbXMyW2ldPVwiQVwiKTsgLy8gdGhlIHNhbWUgYXMgYWJvdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcC5zcGxpY2UoaSsrLCAwLCBbXCJDXCJdW2NvbmNhdF0ocGkuc3BsaWNlKDAsIDYpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwcC5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpaSA9IG1tYXgocC5sZW5ndGgsIHAyICYmIHAyLmxlbmd0aCB8fCAwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZml4TSA9IGZ1bmN0aW9uIChwYXRoMSwgcGF0aDIsIGExLCBhMiwgaSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocGF0aDEgJiYgcGF0aDIgJiYgcGF0aDFbaV1bMF0gPT0gXCJNXCIgJiYgcGF0aDJbaV1bMF0gIT0gXCJNXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGgyLnNwbGljZShpLCAwLCBbXCJNXCIsIGEyLngsIGEyLnldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLmJ4ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLmJ5ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLnggPSBwYXRoMVtpXVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLnkgPSBwYXRoMVtpXVsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlpID0gbW1heChwLmxlbmd0aCwgcDIgJiYgcDIubGVuZ3RoIHx8IDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwY29tczEgPSBbXSwgLy8gcGF0aCBjb21tYW5kcyBvZiBvcmlnaW5hbCBwYXRoIHBcbiAgICAgICAgICAgICAgICBwY29tczIgPSBbXSwgLy8gcGF0aCBjb21tYW5kcyBvZiBvcmlnaW5hbCBwYXRoIHAyXG4gICAgICAgICAgICAgICAgcGZpcnN0ID0gXCJcIiwgLy8gdGVtcG9yYXJ5IGhvbGRlciBmb3Igb3JpZ2luYWwgcGF0aCBjb21tYW5kXG4gICAgICAgICAgICAgICAgcGNvbSA9IFwiXCI7IC8vIGhvbGRlciBmb3IgcHJldmlvdXMgcGF0aCBjb21tYW5kIG9mIG9yaWdpbmFsIHBhdGhcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG1tYXgocC5sZW5ndGgsIHAyICYmIHAyLmxlbmd0aCB8fCAwKTsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwW2ldICYmIChwZmlyc3QgPSBwW2ldWzBdKTsgLy8gc2F2ZSBjdXJyZW50IHBhdGggY29tbWFuZFxuXG4gICAgICAgICAgICAgICAgaWYgKHBmaXJzdCAhPSBcIkNcIikgLy8gQyBpcyBub3Qgc2F2ZWQgeWV0LCBiZWNhdXNlIGl0IG1heSBiZSByZXN1bHQgb2YgY29udmVyc2lvblxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcGNvbXMxW2ldID0gcGZpcnN0OyAvLyBTYXZlIGN1cnJlbnQgcGF0aCBjb21tYW5kXG4gICAgICAgICAgICAgICAgICAgIGkgJiYgKCBwY29tID0gcGNvbXMxW2ktMV0pOyAvLyBHZXQgcHJldmlvdXMgcGF0aCBjb21tYW5kIHBjb21cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcFtpXSA9IHByb2Nlc3NQYXRoKHBbaV0sIGF0dHJzLCBwY29tKTsgLy8gUHJldmlvdXMgcGF0aCBjb21tYW5kIGlzIGlucHV0dGVkIHRvIHByb2Nlc3NQYXRoXG5cbiAgICAgICAgICAgICAgICBpZiAocGNvbXMxW2ldICE9IFwiQVwiICYmIHBmaXJzdCA9PSBcIkNcIikgcGNvbXMxW2ldID0gXCJDXCI7IC8vIEEgaXMgdGhlIG9ubHkgY29tbWFuZFxuICAgICAgICAgICAgICAgIC8vIHdoaWNoIG1heSBwcm9kdWNlIG11bHRpcGxlIEM6c1xuICAgICAgICAgICAgICAgIC8vIHNvIHdlIGhhdmUgdG8gbWFrZSBzdXJlIHRoYXQgQyBpcyBhbHNvIEMgaW4gb3JpZ2luYWwgcGF0aFxuXG4gICAgICAgICAgICAgICAgZml4QXJjKHAsIGkpOyAvLyBmaXhBcmMgYWRkcyBhbHNvIHRoZSByaWdodCBhbW91bnQgb2YgQTpzIHRvIHBjb21zMVxuXG4gICAgICAgICAgICAgICAgaWYgKHAyKSB7IC8vIHRoZSBzYW1lIHByb2NlZHVyZXMgaXMgZG9uZSB0byBwMlxuICAgICAgICAgICAgICAgICAgICBwMltpXSAmJiAocGZpcnN0ID0gcDJbaV1bMF0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGZpcnN0ICE9IFwiQ1wiKVxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwY29tczJbaV0gPSBwZmlyc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICBpICYmIChwY29tID0gcGNvbXMyW2ktMV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHAyW2ldID0gcHJvY2Vzc1BhdGgocDJbaV0sIGF0dHJzMiwgcGNvbSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBjb21zMltpXSE9XCJBXCIgJiYgcGZpcnN0PT1cIkNcIikgcGNvbXMyW2ldPVwiQ1wiO1xuXG4gICAgICAgICAgICAgICAgICAgIGZpeEFyYyhwMiwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpeE0ocCwgcDIsIGF0dHJzLCBhdHRyczIsIGkpO1xuICAgICAgICAgICAgICAgIGZpeE0ocDIsIHAsIGF0dHJzMiwgYXR0cnMsIGkpO1xuICAgICAgICAgICAgICAgI
57590HZhciBzZWcgPSBwW2ldLFxuICAgICAgICAgICAgICAgICAgICBzZWcyID0gcDIgJiYgcDJbaV0sXG4gICAgICAgICAgICAgICAgICAgIHNlZ2xlbiA9IHNlZy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIHNlZzJsZW4gPSBwMiAmJiBzZWcyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBhdHRycy54ID0gc2VnW3NlZ2xlbiAtIDJdO1xuICAgICAgICAgICAgICAgIGF0dHJzLnkgPSBzZWdbc2VnbGVuIC0gMV07XG4gICAgICAgICAgICAgICAgYXR0cnMuYnggPSB0b0Zsb2F0KHNlZ1tzZWdsZW4gLSA0XSkgfHwgYXR0cnMueDtcbiAgICAgICAgICAgICAgICBhdHRycy5ieSA9IHRvRmxvYXQoc2VnW3NlZ2xlbiAtIDNdKSB8fCBhdHRycy55O1xuICAgICAgICAgICAgICAgIGF0dHJzMi5ieCA9IHAyICYmICh0b0Zsb2F0KHNlZzJbc2VnMmxlbiAtIDRdKSB8fCBhdHRyczIueCk7XG4gICAgICAgICAgICAgICAgYXR0cnMyLmJ5ID0gcDIgJiYgKHRvRmxvYXQoc2VnMltzZWcybGVuIC0gM10pIHx8IGF0dHJzMi55KTtcbiAgICAgICAgICAgICAgICBhdHRyczIueCA9IHAyICYmIHNlZzJbc2VnMmxlbiAtIDJdO1xuICAgICAgICAgICAgICAgIGF0dHJzMi55ID0gcDIgJiYgc2VnMltzZWcybGVuIC0gMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXAyKSB7XG4gICAgICAgICAgICAgICAgcHRoLmN1cnZlID0gcGF0aENsb25lKHApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHAyID8gW3AsIHAyXSA6IHA7XG4gICAgICAgIH0sIG51bGwsIHBhdGhDbG9uZSksXG4gICAgICAgIHBhcnNlRG90cyA9IFIuX3BhcnNlRG90cyA9IGNhY2hlcihmdW5jdGlvbiAoZ3JhZGllbnQpIHtcbiAgICAgICAgICAgIHZhciBkb3RzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBncmFkaWVudC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvdCA9IHt9LFxuICAgICAgICAgICAgICAgICAgICBwYXIgPSBncmFkaWVudFtpXS5tYXRjaCgvXihbXjpdKik6PyhbXFxkXFwuXSopLyk7XG4gICAgICAgICAgICAgICAgZG90LmNvbG9yID0gUi5nZXRSR0IocGFyWzFdKTtcbiAgICAgICAgICAgICAgICBpZiAoZG90LmNvbG9yLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkb3Qub3BhY2l0eSA9IGRvdC5jb2xvci5vcGFjaXR5O1xuICAgICAgICAgICAgICAgIGRvdC5jb2xvciA9IGRvdC5jb2xvci5oZXg7XG4gICAgICAgICAgICAgICAgcGFyWzJdICYmIChkb3Qub2Zmc2V0ID0gcGFyWzJdICsgXCIlXCIpO1xuICAgICAgICAgICAgICAgIGRvdHMucHVzaChkb3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChpID0gMSwgaWkgPSBkb3RzLmxlbmd0aCAtIDE7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb3RzW2ldLm9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgc3RhcnQgPSB0b0Zsb2F0KGRvdHNbaSAtIDFdLm9mZnNldCB8fCAwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSBpICsgMTsgaiA8IGlpOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb3RzW2pdLm9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IGRvdHNbal0ub2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSAxMDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBqID0gaWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZW5kID0gdG9GbG9hdChlbmQpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZCA9IChlbmQgLSBzdGFydCkgLyAoaiAtIGkgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICg7IGkgPCBqOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ICs9IGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb3RzW2ldLm9mZnNldCA9IHN0YXJ0ICsgXCIlXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZG90cztcbiAgICAgICAgfSksXG4gICAgICAgIHRlYXIgPSBSLl90ZWFyID0gZnVuY3Rpb24gKGVsLCBwYXBlcikge1xuICAgICAgICAgICAgZWwgPT0gcGFwZXIudG9wICYmIChwYXBlci
5759050b3AgPSBlbC5wcmV2KTtcbiAgICAgICAgICAgIGVsID09IHBhcGVyLmJvdHRvbSAmJiAocGFwZXIuYm90dG9tID0gZWwubmV4dCk7XG4gICAgICAgICAgICBlbC5uZXh0ICYmIChlbC5uZXh0LnByZXYgPSBlbC5wcmV2KTtcbiAgICAgICAgICAgIGVsLnByZXYgJiYgKGVsLnByZXYubmV4dCA9IGVsLm5leHQpO1xuICAgICAgICB9LFxuICAgICAgICB0b2Zyb250ID0gUi5fdG9mcm9udCA9IGZ1bmN0aW9uIChlbCwgcGFwZXIpIHtcbiAgICAgICAgICAgIGlmIChwYXBlci50b3AgPT09IGVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGVhcihlbCwgcGFwZXIpO1xuICAgICAgICAgICAgZWwubmV4dCA9IG51bGw7XG4gICAgICAgICAgICBlbC5wcmV2ID0gcGFwZXIudG9wO1xuICAgICAgICAgICAgcGFwZXIudG9wLm5leHQgPSBlbDtcbiAgICAgICAgICAgIHBhcGVyLnRvcCA9IGVsO1xuICAgICAgICB9LFxuICAgICAgICB0b2JhY2sgPSBSLl90b2JhY2sgPSBmdW5jdGlvbiAoZWwsIHBhcGVyKSB7XG4gICAgICAgICAgICBpZiAocGFwZXIuYm90dG9tID09PSBlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRlYXIoZWwsIHBhcGVyKTtcbiAgICAgICAgICAgIGVsLm5leHQgPSBwYXBlci5ib3R0b207XG4gICAgICAgICAgICBlbC5wcmV2ID0gbnVsbDtcbiAgICAgICAgICAgIHBhcGVyLmJvdHRvbS5wcmV2ID0gZWw7XG4gICAgICAgICAgICBwYXBlci5ib3R0b20gPSBlbDtcbiAgICAgICAgfSxcbiAgICAgICAgaW5zZXJ0YWZ0ZXIgPSBSLl9pbnNlcnRhZnRlciA9IGZ1bmN0aW9uIChlbCwgZWwyLCBwYXBlcikge1xuICAgICAgICAgICAgdGVhcihlbCwgcGFwZXIpO1xuICAgICAgICAgICAgZWwyID09IHBhcGVyLnRvcCAmJiAocGFwZXIudG9wID0gZWwpO1xuICAgICAgICAgICAgZWwyLm5leHQgJiYgKGVsMi5uZXh0LnByZXYgPSBlbCk7XG4gICAgICAgICAgICBlbC5uZXh0ID0gZWwyLm5leHQ7XG4gICAgICAgICAgICBlbC5wcmV2ID0gZWwyO1xuICAgICAgICAgICAgZWwyLm5leHQgPSBlbDtcbiAgICAgICAgfSxcbiAgICAgICAgaW5zZXJ0YmVmb3JlID0gUi5faW5zZXJ0YmVmb3JlID0gZnVuY3Rpb24gKGVsLCBlbDIsIHBhcGVyKSB7XG4gICAgICAgICAgICB0ZWFyKGVsLCBwYXBlcik7XG4gICAgICAgICAgICBlbDIgPT0gcGFwZXIuYm90dG9tICYmIChwYXBlci
575905ib3R0b20gPSBlbCk7XG4gICAgICAgICAgICBlbDIucHJldiAmJiAoZWwyLnByZXYubmV4dCA9IGVsKTtcbiAgICAgICAgICAgIGVsLnByZXYgPSBlbDIucHJldjtcbiAgICAgICAgICAgIGVsMi5wcmV2ID0gZWw7XG4gICAgICAgICAgICBlbC5uZXh0ID0gZWwyO1xuICAgICAgICB9LFxuICAgICAgICAvKlxcXG4gICAgICAgICAqIFJhcGhhZWwudG9NYXRyaXhcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSZXR1cm5zIG1hdHJpeCBvZiB0cmFuc2Zvcm1hdGlvbnMgYXBwbGllZCB0byBhIGdpdmVuIHBhdGhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBwYXRoIChzdHJpbmcpIHBhdGggc3RyaW5nXG4gICAgICAgICAtIHRyYW5zZm9ybSAoc3RyaW5nfGFycmF5KSB0cmFuc2Zvcm1hdGlvbiBzdHJpbmdcbiAgICAgICAgID0gKG9iamVjdCkgQE1hdHJpeFxuICAgICAgICBcXCovXG4gICAgICAgIHRvTWF0cml4ID0gUi50b01hdHJpeCA9IGZ1bmN0aW9uIChwYXRoLCB0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIHZhciBiYiA9IHBhdGhEaW1lbnNpb25zKHBhdGgpLFxuICAgICAgICAgICAgICAgIGVsID0ge1xuICAgICAgICAgICAgICAgICAgICBfOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IEVcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZ2V0QkJveDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGV4dHJhY3RUcmFuc2Zvcm0oZWwsIHRyYW5zZm9ybSk7XG4gICAgICAgICAgICByZXR1cm4gZWwubWF0cml4O1xuICAgICAgICB9LFxuICAgICAgICAvKlxcXG4gICAgICAgICAqIFJhcGhhZWwudHJhbnNmb3JtUGF0aFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgICAgICoqXG4gICAgICAgICAqIFJldHVybnMgcGF0aCB0cmFuc2Zvcm1lZCBieSBhIGdpdmVuIHRyYW5zZm9ybWF0aW9uXG4gICAgICAgICA+IFBhcmFtZXRlcnNcbiAgICAgICAgIC0gcGF0aCAoc3RyaW5nKSBwYXRoIHN0cmluZ1xuICAgICAgICAgLSB0cmFuc2Zvcm0gKHN0cmluZ3xhcnJheSkgdHJhbnNmb3JtYXRpb24gc3RyaW5nXG4gICAgICAgICA9IChzdHJpbmcpIHBhdGhcbiAgICAgICAgXFwqL1xuICAgICAgICB0cmFuc2Zvcm1QYXRoID0gUi50cmFuc2Zvcm1QYXRoID0gZnVuY3Rpb24gKHBhdGgsIHRyYW5zZm9ybSkge1xuICAgICAgICAgICAgcmV0dXJuIG1hcFBhdGgocGF0aCwgdG9NYXRyaXgocGF0aCwgdHJhbnNmb3JtKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGV4dHJhY3RUcmFuc2Zvcm0gPSBSLl9leHRyYWN0VHJhbnNmb3JtID0gZnVuY3Rpb24gKGVsLCB0c3RyKSB7XG4gICAgICAgICAgICBpZiAodHN0ciA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsLl8udHJhbnNmb3JtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHN0ciA9IFN0cih0c3RyKS5yZXBsYWNlKC9cXC57M318XFx1MjAyNi9nLCBlbC5fLnRyYW5zZm9ybSB8fCBFKTtcbiAgICAgICAgICAgIHZhciB0ZGF0YSA9IFIucGFyc2VUcmFuc2Zvcm1TdHJpbmcodHN0ciksXG4gICAgICAgICAgICAgICAgZGVnID0gMCxcbiAgICAgICAgICAgICAgICBkeCA9IDAsXG4gICAgICAgICAgICAgICAgZHkgPSAwLFxuICAgICAgICAgICAgICAgIHN4ID0gMSxcbiAgICAgICAgICAgICAgICBzeSA9IDEsXG4gICAgICAgICAgICAgICAgXyA9IGVsLl8sXG4gICAgICAgICAgICAgICAgbSA9IG5ldyBNYXRyaXg7XG4gICAgICAgICAgICBfLnRyYW5zZm9ybSA9IHRkYXRhIHx8IFtdO1xuICAgICAgICAgICAgaWYgKHRkYXRhKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGRhdGEubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgdCA9IHRkYXRhW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGxlbiA9IHQubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29tbWFuZCA9IFN0cih0WzBdKS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYWJzb2x1dGUgPSB0WzBdICE9IGNvbW1hbmQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnZlciA9IGFic29sdXRlID8gbS5pbnZlcnQoKSA6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICB4MSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHkxLFxuICAgICAgICAgICAgICAgICAgICAgICAgeDIsXG4gICAgICAgICAgICAgICAgICAgICAgICB5MixcbiAgICAgICAgICAgICAgICAgICAgICAgIGJiO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29tbWFuZCA9PSBcInRcIiAmJiB0bGVuID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgxID0gaW52ZXIueCgwLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5MSA9IGludmVyLnkoMCwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeDIgPSBpbnZlci54KHRbMV0sIHRbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gaW52ZXIueSh0WzFdLCB0WzJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLnRyYW5zbGF0ZSh4MiAtIHgxLCB5MiAtIHkxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbS50cmFuc2xhdGUodFsxXSwgdFsyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY29tbWFuZCA9PSBcInJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRsZW4gPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJiID0gYmIgfHwgZWwuZ2V0QkJveCgxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLnJvdGF0ZSh0WzFdLCBiYi54ICsgYmIud2lkdGggLyAyLCBiYi55ICsgYmIuaGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVnICs9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRsZW4gPT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MiA9IGludmVyLngodFsyXSwgdFszXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gaW52ZXIueSh0WzJdLCB0WzNdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5yb3RhdGUodFsxXSwgeDIsIHkyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLnJvdGF0ZSh0WzFdLCB0WzJdLCB0WzNdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVnICs9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY29tbWFuZCA9PSBcInNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRsZW4gPT0gMiB8fCB0bGVuID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYiA9IGJiIHx8IGVsLmdldEJCb3goMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5zY2FsZSh0WzFdLCB0W3RsZW4gLSAxXSwgYmIueCArIGJiLndpZHRoIC8gMiwgYmIueSArIGJiLmhlaWdodCAvIDIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN4ICo9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3kgKj0gdFt0bGVuIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRsZW4gPT0gNSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MiA9IGludmVyLngodFszXSwgdFs0XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gaW52ZXIueSh0WzNdLCB0WzRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5zY2FsZSh0WzFdLCB0WzJdLCB4MiwgeTIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG0uc2NhbGUodFsxXSwgdFsyXSwgdFszXSwgdFs0XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN4ICo9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3kgKj0gdFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjb21tYW5kID09IFwibVwiICYmIHRsZW4gPT0gNykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbS5hZGQodFsxXSwgdFsyXSwgdFszXSwgdFs0XSwgdFs1XSwgdFs2XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgXy5kaXJ0eVQgPSAxO1xuICAgICAgICAgICAgICAgICAgICBlbC5tYXRyaXggPSBtO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLypcXFxuICAgICAgICAgICAgICogRWxlbWVudC5tYXRyaXhcbiAgICAgICAgICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgICAgICAgICAqKlxuICAgICAgICAgICAgICogS2VlcHMgQE1hdHJpeCBvYmplY3QsIHdoaWNoIHJlcHJlc2VudHMgZWxlbWVudCB0cmFuc2Zvcm1hdGlvblxuICAgICAgICAgICAgXFwqL1xuICAgICAgICAgICAgZWwubWF0cml4ID0gbTtcblxuICAgICAgICAgICAgXy5zeCA9IHN4O1xuICAgICAgICAgICAgXy5zeSA9IHN5O1xuICAgICAgICAgICAgXy5kZWcgPSBkZWc7XG4gICAgICAgICAgICBfLmR4ID0gZHggPSBtLmU7XG4gICAgICAgICAgICBfLmR5ID0gZHkgPSBtLmY7XG5cbiAgICAgICAgICAgIGlmIChzeCA9PSAxICYmIHN5ID09IDEgJiYgIWRlZyAmJiBfLmJib3gpIHtcbiAgICAgICAgICAgICAgICBfLmJib3gueCArPSArZHg7XG4gICAgICAgICAgICAgICAgXy5iYm94
57590LnkgKz0gK2R5O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBfLmRpcnR5VCA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGdldEVtcHR5ID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgIHZhciBsID0gaXRlbVswXTtcbiAgICAgICAgICAgIHN3aXRjaCAobC50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcInRcIjogcmV0dXJuIFtsLCAwLCAwXTtcbiAgICAgICAgICAgICAgICBjYXNlIFwibVwiOiByZXR1cm4gW2wsIDEsIDAsIDAsIDEsIDAsIDBdO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJyXCI6IGlmIChpdGVtLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbbCwgMCwgaXRlbVsyXSwgaXRlbVszXV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtsLCAwXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSBcInNcIjogaWYgKGl0ZW0ubGVuZ3RoID09IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtsLCAxLCAxLCBpdGVtWzNdLCBpdGVtWzRdXTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGl0ZW0ubGVuZ3RoID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtsLCAxLCAxXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2wsIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXF1YWxpc2VUcmFuc2Zvcm0gPSBSLl9lcXVhbGlzZVRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0MSwgdDIpIHtcbiAgICAgICAgICAgIHQyID0gU3RyKHQyKS5yZXBsYWNlKC9cXC57M318XFx1MjAyNi9nLCB0MSk7XG4gICAgICAgICAgICB0MSA9IFIucGFyc2VUcmFuc2Zvcm1TdHJpbmcodDEpIHx8IFtdO1xuICAgICAgICAgICAgdDIgPSBSLnBhcnNlVHJhbnNmb3JtU3RyaW5nKHQyKSB8fCBbXTtcbiAgICAgICAgICAgIHZhciBtYXhsZW5ndGggPSBtbWF4KHQxLmxlbmd0aCwgdDIubGVuZ3RoKSxcbiAgICAgICAgICAgICAgICBmcm9tID0gW10sXG4gICAgICAgICAgICAgICAgdG8gPSBbXSxcbiAgICAgICAgICAgICAgICBpID0gMCwgaiwgamosXG4gICAgICAgICAgICAgICAgdHQxLCB0dDI7XG4gICAgICAgICAgICBmb3IgKDsgaSA8IG1heGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdHQxID0gdDFbaV0gfHwgZ2V0RW1wdHkodDJbaV0pO1xuICAgICAgICAgICAgICAgIHR0MiA9IHQyW2ldIHx8IGdldEVtcHR5KHR0MSk7XG4gICAgICAgICAgICAgICAgaWYgKCh0dDFbMF0gIT0gdHQyWzBdKSB8fFxuICAgICAgICAgICAgICAgICAgICAodHQxWzBdLnRvTG93ZXJDYXNlKCkgPT0gXCJyXCIgJiYgKHR0MVsyXSAhPSB0dDJbMl0gfHwgdHQxWzNdICE9IHR0MlszXSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICh0dDFbMF0udG9Mb3dlckNhc2UoKSA9PSBcInNcIiAmJiAodHQxWzNdICE9IHR0MlszXSB8fCB0dDFbNF0gIT0gdHQyWzRdKSlcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnJvbVtpXSA9IFtdO1xuICAgICAgICAgICAgICAgIHRvW2ldID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMCwgamogPSBtbWF4KHR0MS5sZW5ndGgsIHR0Mi5sZW5ndGgpOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBqIGluIHR0MSAmJiAoZnJvbVtpXVtqXSA9IHR0MVtqXSk7XG4gICAgICAgICAgICAgICAgICAgIGogaW4gdHQyICYmICh0b1tpXVtqXSA9IHR0MltqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmcm9tOiBmcm9tLFxuICAgICAgICAgICAgICAgIHRvOiB0b1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICBSLl9nZXRDb250YWluZXIgPSBmdW5jdGlvbiAoeCwgeSwgdywgaCkge1xuICAgICAgICB2Y
57590XIgY29udGFpbmVyO1xuICAgICAgICBjb250YWluZXIgPSBoID09IG51bGwgJiYgIVIuaXMoeCwgXCJvYmplY3RcIikgPyBnLmRvYy5nZXRFbGVtZW50QnlJZCh4KSA6IHg7XG4gICAgICAgIGlmIChjb250YWluZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb250YWluZXIudGFnTmFtZSkge1xuICAgICAgICAgICAgaWYgKHkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogY29udGFpbmVyLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogY29udGFpbmVyLnN0eWxlLnBpeGVsV2lkdGggfHwgY29udGFpbmVyLm9mZnNldFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGNvbnRhaW5lci5zdHlsZS5waXhlbEhlaWdodCB8fCBjb250YWluZXIub2Zmc2V0SGVpZ2h0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiB5LFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHdcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250YWluZXI6IDEsXG4gICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgeTogeSxcbiAgICAgICAgICAgIHdpZHRoOiB3LFxuICAgICAgICAgICAgaGVpZ2h0OiBoXG4gICAgICAgIH07XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5wYXRoVG9SZWxhdGl2ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBwYXRoIHRvIHJlbGF0aXZlIGZvcm1cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gcGF0aFN0cmluZyAoc3RyaW5nfGFycmF5KSBwYXRoIHN0cmluZyBvciBhcnJheSBvZiBzZWdtZW50c1xuICAgICA9IChhcnJheSkgYXJyYXkgb2Ygc2VnbWVudHMuXG4gICAgXFwqL1xuICAgIFIucGF0aFRvUmVsYXRpdmUgPSBwYXRoVG9SZWxhdGl2ZTtcbiAgICBSLl9lbmdpbmUgPSB7fTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5wYXRoMmN1cnZlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBVdGlsaXR5IG1ldGhvZFxuICAgICAqKlxuICAgICAqIENvbnZlcnRzIHBhdGggdG8gYSBuZXcgcGF0aCB3aGVyZSBhbGwgc2VnbWVudHMgYXJlIGN1YmljIGJlemllciBjdXJ2ZXMuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHBhdGhTdHJpbmcgKHN0cmluZ3xhcnJheSkgcGF0aCBzdHJpbmcgb3IgYXJyYXkgb2Ygc2VnbWVudHNcbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIHNlZ21lbnRzLlxuICAgIFxcKi9cbiAgICBSLnBhdGgyY3VydmUgPSBwYXRoMmN1cnZlO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLm1hdHJpeFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIG1hdHJpeCBiYXNlZCBvbiBnaXZlbiBwYXJhbWV0ZXJzLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBhIChudW1iZXIpXG4gICAgIC0gYiAobnVtYmVyKVxuICAgICAtIGMgKG51bWJlcilcbiAgICAgLSBkIChudW1iZXIpXG4gICAgIC0gZSAobnVtYmVyKVxuICAgICAtIGYgKG51bWJlcilcbiAgICAgPSAob2JqZWN0KSBATWF0cml4XG4gICAgXFwqL1xuICAgIFIubWF0cml4ID0gZnVuY3Rpb24gKGEsIGIsIGMsIGQsIGUsIGYpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgoYSwgYiwgYywgZCwgZSwgZik7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBNYXRyaXgoYSwgYiwgYywgZCwgZSwgZikge1xuICAgICAgICBpZiAoYSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmEgPSArYTtcbiAgICAgICAgICAgIHRoaXMuYiA9ICtiO1xuICAgICAgICAgICAgdGhpcy5jID0gK2M7XG4gICAgICAgICAgICB0aGlzLmQgPSArZDtcbiAgICAgICAgICAgIHRoaXMuZSA9ICtlO1xuICAgICAgICAgICAgdGhpcy5mID0gK2Y7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmEgPSAxO1xuICAgICAgICAgICAgdGhpcy5iID0gMDtcbiAgICAgICAgICAgIHRoaXMuYyA9IDA7XG4gICAgICAgICAgICB0aGlzLmQgPSAxO1xuICAgICAgICAgICAgdGhpcy5lID0gMDtcbiAgICAgICAgICAgIHRoaXMuZiA9IDA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgKGZ1bmN0aW9uIChtYXRyaXhwcm90bykge1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC5hZGRcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIEFkZHMgZ2l2ZW4gbWF0cml4IHRvIGV4aXN0aW5nIG9uZS5cbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBhIChudW1iZXIpXG4gICAgICAgICAtIGIgKG51bWJlcilcbiAgICAgICAgIC0gYyAobnVtYmVyKVxuICAgICAgICAgLSBkIChudW1iZXIpXG4gICAgICAgICAtIGUgKG51bWJlcilcbiAgICAgICAgIC0gZiAobnVtYmVyKVxuICAgICAgICAgb3JcbiAgICAgICAgIC0gbWF0cml4IChvYmplY3QpIEBNYXRyaXhcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5hZGQgPSBmdW5jdGlvbiAoYSwgYiwgYywgZCwgZSwgZikge1xuICAgICAgICAgICAgdmFyIG91dCA9IFtbXSwgW10sIFtdXSxcbiAgICAgICAgICAgICAgICBtID0gW1t0aGlzLmEsIHRoaXMuYywgdGhpcy5lXSwgW3RoaXMuYiwgdGhpcy5kLCB0aGlzLmZdLCBbMCwgMCwgMV1dLFxuICAgICAgICAgICAgICAgIG1hdHJpeCA9IFtbYSwgYywgZV0sIFtiLCBkLCBmXSwgWzAsIDAsIDFdXSxcbiAgICAgICAgICAgICAgICB4LCB5LCB6LCByZXM7XG5cbiAgICAgICAgICAgIGlmIChhICYmIGEgaW5zdGFuY2VvZiBNYXRyaXgpIHtcbiAgICAgICAgICAgICAgICBtYXRyaXggPSBbW2EuYSwgYS5jLCBhLmVdLCBbYS5iLCBhLmQsIGEuZl0sIFswLCAwLCAxXV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHggPCAzOyB4KyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKHkgPSAwOyB5IDwgMzsgeSsrKSB7XG4gICAgICAgICAgICAgICAgICAgI
57590HJlcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoeiA9IDA7IHogPCAzOyB6KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcyArPSBtW3hdW3pdICogbWF0cml4W3pdW3ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG91dFt4XVt5XSA9IHJlcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmEgPSBvdXRbMF1bMF07XG4gICAgICAgICAgICB0aGlzLmIgPSBvdXRbMV1bMF07XG4gICAgICAgICAgICB0aGlzLmMgPSBvdXRbMF1bMV07XG4gICAgICAgICAgICB0aGlzLmQgPSBvdXRbMV1bMV07XG4gICAgICAgICAgICB0aGlzLmUgPSBvdXRbMF1bMl07XG4gICAgICAgICAgICB0aGlzLmYgPSBvdXRbMV1bMl07XG4gICAgICAgIH07XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogTWF0cml4LmludmVydFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogUmV0dXJucyBpbnZlcnRlZCB2ZXJzaW9uIG9mIHRoZSBtYXRyaXhcbiAgICAgICAgID0gKG9iamVjdCkgQE1hdHJpeFxuICAgICAgICBcXCovXG4gICAgICAgIG1hdHJpeHByb3RvLmludmVydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBtZSA9IHRoaXMsXG4gICAgICAgICAgICAgICAgeCA9IG1lLmEgKiBtZS5kIC0gbWUuYiAqIG1lLmM7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeChtZS5kIC8geCwgLW1lLmIgLyB4LCAtbWUuYyAvIHgsIG1lLmEgLyB4LCAobWUuYyAqIG1lLmYgLSBtZS5kICogbWUuZSkgLyB4LCAobWUuYiAqIG1lLmUgLSBtZS5hICogbWUuZikgLyB4KTtcbiAgICAgICAgfTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBNYXRyaXguY2xvbmVcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFJldHVybnMgY29weSBvZiB0aGUgbWF0cml4XG4gICAgICAgICA9IChvYmplY3QpIEBNYXRyaXhcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4KHRoaXMuYSwgdGhpcy5iLCB0aGlzLmMsIHRoaXMuZCwgdGhpcy5lLCB0aGlzLmYpO1xuICAgICAgICB9O1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC50cmFuc2xhdGVcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFRyYW5zbGF0ZSB0aGUgbWF0cml4XG4gICAgICAgICA+IFBhcmFtZXRlcnNcbiAgICAgICAgIC0geCAobnVtYmVyKVxuICAgICAgICAgLSB5IChudW1iZXIpXG4gICAgICAgIFxcKi9cbiAgICAgICAgbWF0cml4cHJvdG8udHJhbnNsYXRlID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkKDEsIDAsIDAsIDEsIHgsIHkpO1xuICAgICAgICB9O1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC5zY2FsZVxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogU2NhbGVzIHRoZSBtYXRyaXhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSB4IChudW1iZXIpXG4gICAgICAgICAtIHkgKG51bWJlcikgI29wdGlvbmFsXG4gICAgICAgICAtIGN4IChudW1iZXIpICNvcHRpb25hbFxuICAgICAgICAgLSBjeSAobnVtYmVyKSAjb3B0aW9uYWxcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5zY2FsZSA9IGZ1bmN0aW9uICh4LCB5LCBjeCwgY3kpIHtcbiAgICAgICAgICAgIHkgPT0gbnVsbCAmJiAoeSA9IHgpO1xuICAgICAgICAgICAgKGN4IHx8IGN5KSAmJiB0aGlzLmFkZCgxLCAwLCAwLCAxLCBjeCwgY3kpO1xuICAgICAgICAgICAgdGhpcy5hZGQoeCwgMCwgMCwgeSwgMCwgMCk7XG4gICAgICAgICAgICAoY3ggfHwgY3kpICYmIHRoaXMuYWRkKDEsIDAsIDAsIDEsIC1jeCwgLWN5KTtcbiAgICAgICAgfTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBNYXRyaXgucm90YXRlXG4gICAgICAgICBbIG1ldGhvZCBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSb3RhdGVzIHRoZSBtYXRyaXhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBhIChudW1iZXIpXG4gICAgICAgICAtIHggKG51bWJlcilcbiAgICAgICAgIC0geSAobnVtYmVyKVxuICAgICAgICBcXCovXG4gICAgICAgIG1hdHJpeHByb3RvLnJvdGF0ZSA9IGZ1bmN0aW9uIChhLCB4LCB5KSB7XG4gICAgICAgICAgICBhID0gUi5yYWQoYSk7XG4gICAgICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICAgICAgeSA9IHkgfHwgMDtcbiAgICAgICAgICAgIHZhciBjb3MgPSArbWF0aC5jb3MoYSkudG9GaXhlZCg5KSxcbiAgICAgICAgICAgICAgICBzaW4gPSArbWF0aC5zaW4oYSkudG9GaXhlZCg5KTtcbiAgICAgICAgICAgIHRoaXMuYWRkKGNvcywgc2luLCAtc2luLCBjb3MsIHgsIHkpO1xuICAgICAgICAgICAgdGhpcy5hZGQoMSwgMCwgMCwgMSwgLXgsIC15KTtcbiAgICAgICAgfTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBNYXRyaXgueFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogUmV0dXJuIHggY29vcmRpbmF0ZSBmb3IgZ2l2ZW4gcG9pbnQgYWZ0ZXIgdHJhbnNmb3JtYXRpb24gZGVzY3JpYmVkIGJ5IHRoZSBtYXRyaXguIFNlZSBhbHNvIEBNYXRyaXgueVxuICAgICAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICAgICAtIHggKG51bWJlcilcbiAgICAgICAgIC0geSAobnVtYmVyKVxuICAgICAgICAgPSAobnVtYmVyKSB4XG4gICAgICAgIFxcKi9cbiAgICAgICAgbWF0cml4cHJvdG8ueCA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgICAgICByZXR1cm4geCAqIHRoaXMuYSArIHkgKiB0aGlzLmMgKyB0aGlzLmU7XG4gICAgICAgIH07XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogTWF0cml4LnlcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFJldHVybiB5IGNvb3JkaW5hdGUgZm9yIGdpdmVuIHBvaW50IGFmdGVyIHRyYW5zZm9ybWF0aW9uIGRlc2NyaWJlZCBieSB0aGUgbWF0cml4LiBTZWUgYWxzbyBATWF0cml4LnhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSB4IChudW1iZXIpXG4gICAgICAgICAtIHkgKG51bWJlcilcbiAgICAgICAgID0gKG51bWJlcikgeVxuICAgICAgICBcXCovXG4gICAgICAgIG1hdHJpeHByb3RvLnkgPSBmdW5jdGlvbiAoeCwgeSkge1xuICAgICAgICAgICAgcmV0dXJuIHggKiB0aGlzLmIgKyB5ICogdGhpcy5kICsgdGh
57590pcy5mO1xuICAgICAgICB9O1xuICAgICAgICBtYXRyaXhwcm90by5nZXQgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgcmV0dXJuICt0aGlzW1N0ci5mcm9tQ2hhckNvZGUoOTcgKyBpKV0udG9GaXhlZCg0KTtcbiAgICAgICAgfTtcbiAgICAgICAgbWF0cml4cHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUi5zdmcgP1xuICAgICAgICAgICAgICAgIFwibWF0cml4KFwiICsgW3RoaXMuZ2V0KDApLCB0aGlzLmdldCgxKSwgdGhpcy5nZXQoMiksIHRoaXMuZ2V0KDMpLCB0aGlzLmdldCg0KSwgdGhpcy5nZXQoNSldLmpvaW4oKSArIFwiKVwiIDpcbiAgICAgICAgICAgICAgICBbdGhpcy5nZXQoMCksIHRoaXMuZ2V0KDIpLCB0aGlzLmdldCgxKSwgdGhpcy5nZXQoMyksIDAsIDBdLmpvaW4oKTtcbiAgICAgICAgfTtcbiAgICAgICAgbWF0cml4cHJvdG8udG9GaWx0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJwcm9naWQ6RFhJbWFnZVRyYW5zZm9ybS5NaWNyb3NvZnQuTWF0cml4KE0xMT1cIiArIHRoaXMuZ2V0KDApICtcbiAgICAgICAgICAgICAgICBcIiwgTTEyPVwiICsgdGhpcy5nZXQoMikgKyBcIiwgTTIxPVwiICsgdGhpcy5nZXQoMSkgKyBcIiwgTTIyPVwiICsgdGhpcy5nZXQoMykgK1xuICAgICAgICAgICAgICAgIFwiLCBEeD1cIiArIHRoaXMuZ2V0KDQpICsgXCIsIER5PVwiICsgdGhpcy5nZXQoNSkgKyBcIiwgc2l6aW5nbWV0aG9kPSdhdXRvIGV4cGFuZCcpXCI7XG4gICAgICAgIH07XG4gICAgICAgIG1hdHJpeHByb3RvLm9mZnNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBbdGhpcy5lLnRvRml4ZWQoNCksIHRoaXMuZi50b0ZpeGVkKDQpXTtcbiAgICAgICAgfTtcbiAgICAgICAgZnVuY3Rpb24gbm9ybShhKSB7XG4gICAgICAgICAgICByZXR1cm4gYVswXSAqIGFbMF0gKyBhWzFdICogYVsxXTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBub3JtYWxpemUoYSkge1xuICAgICAgICAgICAgdmFyIG1hZyA9IG1hdGguc3FydChub3JtKGEpKTtcbiAgICAgICAgICAgIGFbMF0gJiYgKGFbMF0gLz0gbWFnKTtcbiAgICAgICAgICAgIGFbMV0gJiYgKGFbMV0gLz0gbWFnKTtcbiAgICAgICAgfVxuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC5zcGxpdFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogU3BsaXRzIG1hdHJpeCBpbnRvIHByaW1pdGl2ZSB0cmFuc2Zvcm1hdGlvbnNcbiAgICAgICAgID0gKG9iamVjdCkgaW4gZm9ybWF0OlxuICAgICAgICAgbyBkeCAobnVtYmVyKSB0cmFuc2xhdGlvbiBieSB4XG4gICAgICAgICBvIGR5IChudW1iZXIpIHRyYW5zbGF0aW9uIGJ5IHlcbiAgICAgICAgIG8gc2NhbGV4IChudW1iZXIpIHNjYWxlIGJ5IHhcbiAgICAgICAgIG8gc2NhbGV5IChudW1iZXIpIHNjYWxlIGJ5IHlcbiAgICAgICAgIG8gc2hlYXIgKG51bWJlcikgc2hlYXJcbiAgICAgICAgIG8gcm90YXRlIChudW1iZXIpIHJvdGF0aW9uIGluIGRlZ1xuICAgICAgICAgbyBpc1NpbXBsZSAoYm9vbGVhbikgY291bGQgaXQgYmUgcmVwcmVzZW50ZWQgdmlhIHNpbXBsZSB0cmFuc2Zvcm1hdGlvbnNcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5z
57590cGxpdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBvdXQgPSB7fTtcbiAgICAgICAgICAgIC8vIHRyYW5zbGF0aW9uXG4gICAgICAgICAgICBvdXQuZHggPSB0aGlzLmU7XG4gICAgICAgICAgICBvdXQuZHkgPSB0aGlzLmY7XG5cbiAgICAgICAgICAgIC8vIHNjYWxlIGFuZCBzaGVhclxuICAgICAgICAgICAgdmFyIHJvdyA9IFtbdGhpcy5hLCB0aGlzLmNdLCBbdGhpcy5iLCB0aGlzLmRdXTtcbiAgICAgICAgICAgIG91dC5zY2FsZXggPSBtYXRoLnNxcnQobm9ybShyb3dbMF0pKTtcbiAgICAgICAgICAgIG5vcm1hbGl6ZShyb3dbMF0pO1xuXG4gICAgICAgICAgICBvdXQuc2hlYXIgPSByb3dbMF1bMF0gKiByb3dbMV1bMF0gKyByb3dbMF1bMV0gKiByb3dbMV1bMV07XG4gICAgICAgICAgICByb3dbMV0gPSBbcm93WzFdWzBdIC0gcm93WzBdWzBdICogb3V0LnNoZWFyLCByb3dbMV1bMV0gLSByb3dbMF1bMV0gKiBvdXQuc2hlYXJdO1xuXG4gICAgICAgICAgICBvdXQuc2NhbGV5ID0gbWF0aC5zcXJ0KG5vcm0ocm93WzFdKSk7XG4gICAgICAgICAgICBub3JtYWxpemUocm93WzFdKTtcbiAgICAgICAgICAgIG91dC5zaGVhciAvPSBvdXQuc2NhbGV5O1xuXG4gICAgICAgICAgICAvLyByb3RhdGlvblxuICAgICAgICAgICAgdmFyIHNpbiA9IC1yb3dbMF1bMV0sXG4gICAgICAgICAgICAgICAgY29zID0gcm93WzFdWzFdO1xuICAgICAgICAgICAgaWYgKGNvcyA8IDApIHtcbiAgICAgICAgICAgICAgICBvdXQucm90YXRlID0gUi5kZWcobWF0aC5hY29zKGNvcykpO1xuICAgICAgICAgICAgICAgIGlmIChzaW4gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dC5yb3RhdGUgPSAzNjAgLSBvdXQucm90YXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb3V0LnJvdGF0ZSA9IFIuZGVnKG1hdGguYXNpbihzaW4pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3V0LmlzU2ltcGxlID0gIStvdXQuc2hlYXIudG9GaXhlZCg5KSAmJiAob3V0LnNjYWxleC50b0ZpeGVkKDkpID09IG91dC5zY2FsZXkudG9GaXhlZCg5KSB8fCAhb3V0LnJvdGF0ZSk7XG4gICAgICAgICAgICBvdXQuaXNTdXBlclNpbXBsZSA9ICErb3V0LnNoZWFyLnRvRml4ZWQoOSkgJiYgb3V0LnNjYWxleC50b0ZpeGVkKDkpID09IG91dC5zY2FsZXkudG9GaXhlZCg5KSAmJiAhb3V0LnJvdGF0ZTtcbiAgICAgICAgICAgIG91dC5ub1JvdGF0aW9uID0gIStvdXQuc2hlYXIudG9GaXhlZCg5KSAmJiAhb3V0LnJvdGF0ZTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogTWF0cml4LnRvVHJhbnNmb3JtU3RyaW5nXG4gICAgICAgICBbIG1ldGhvZCBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSZXR1cm4gdHJhbnNmb3JtIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgZ2l2ZW4gbWF0cml4XG4gICAgICAgICA9IChzdHJpbmcpIHRyYW5zZm9ybSBzdHJpbmdcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by50b1RyYW5zZm9ybVN0cmluZyA9IGZ1bmN0aW9uIChzaG9ydGVyKSB7XG4gICAgICAgICAgICB2Y
57590XIgcyA9IHNob3J0ZXIgfHwgdGhpc1tzcGxpdF0oKTtcbiAgICAgICAgICAgIGlmIChzLmlzU2ltcGxlKSB7XG4gICAgICAgICAgICAgICAgcy5zY2FsZXggPSArcy5zY2FsZXgudG9GaXhlZCg0KTtcbiAgICAgICAgICAgICAgICBzLnNjYWxleSA9ICtzLnNjYWxleS50b0ZpeGVkKDQpO1xuICAgICAgICAgICAgICAgIHMucm90YXRlID0gK3Mucm90YXRlLnRvRml4ZWQoNCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICAocy5keCB8fCBzLmR5ID8gXCJ0XCIgKyBbcy5keCwgcy5keV0gOiBFKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAocy5zY2FsZXggIT0gMSB8fCBzLnNjYWxleSAhPSAxID8gXCJzXCIgKyBbcy5zY2FsZXgsIHMuc2NhbGV5LCAwLCAwXSA6IEUpICtcbiAgICAgICAgICAgICAgICAgICAgICAgIChzLnJvdGF0ZSA/IFwiclwiICsgW3Mucm90YXRlLCAwLCAwXSA6IEUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJtXCIgKyBbdGhpcy5nZXQoMCksIHRoaXMuZ2V0KDEpLCB0aGlzLmdldCgyKSwgdGhpcy5nZXQoMyksIHRoaXMuZ2V0KDQpLCB0aGlzLmdldCg1KV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfSkoTWF0cml4LnByb3RvdHlwZSk7XG5cbiAgICB2YXIgcHJldmVudERlZmF1bHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICB9LFxuICAgIHByZXZlbnRUb3VjaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3JpZ2luYWxFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sXG4gICAgc3RvcFByb3BhZ2F0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNhbmNlbEJ1YmJsZSA9IHRydWU7XG4gICAgfSxcbiAgICBzdG9wVG91Y2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yaWdpbmFsRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSxcbiAgICBnZXRFdmVudFBvc2l0aW9uID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHNjcm9sbFkgPSBnLmRvYy5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGcuZG9jLmJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgc2Nyb2xsWCA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGcuZG9jLmJvZHkuc2Nyb2xsTGVmdDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogZS5jbGllbnRYICsgc2Nyb2xsWCxcbiAgICAgICAgICAgIHk6IGUuY2xpZW50WSArIHNjcm9sbFlcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGFkZEV2ZW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGcuZG9jLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAob2JqLCB0eXBlLCBmbiwgZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHZhciBmID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbi5jYWxsKGVsZW1lbnQsIGUsIHBvcy54LCBwb3MueSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBvYmouYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBmLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoc3VwcG9ydHNUb3VjaCAmJiB0b3VjaE1hcFt0eXBlXSkge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgX2YgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGdldEV2ZW50UG9zaXRpb24oZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkZSA9IGU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGUudGFyZ2V0VG91Y2hlcyAmJiBlLnRhcmdldFRvdWNoZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLnRhcmdldFRvdWNoZXNbaV0udGFyZ2V0ID09IG9iaikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlID0gZS50YXJnZXRUb3VjaGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQgPSBvbGRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0ID0gcHJldmVudFRvdWNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbiA9IHN0b3BUb3VjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbChlbGVtZW50LCBlLCBwb3MueCwgcG9zLnkpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBvYmouYWRkRXZlbnRMaXN0ZW5lcih0b3VjaE1hcFt0eXBlXSwgX2YsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBmLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHN1cHBvcnRzVG91Y2ggJiYgdG91Y2hNYXBbdHlwZV0pXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcih0b3VjaE1hcFt0eXBlXSwgX2YsIGZhbHNlKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmIChnLmRvYy5hdHRhY2hFdmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChvYmosIHR5cGUsIGZuLCBlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIGYgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBlID0gZSB8fCBnLndpbi5ldmVudDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNjcm9sbFkgPSBnLmRvYy5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGcuZG9jLmJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGcuZG9jLmJvZHkuc2Nyb2xsTGVmdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBlLmNsaWVudFggKyBzY3JvbGxYLFxuICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGUuY2xpZW50WSArIHNjcm9sbFk7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQgPSBlLnByZXZlbnREZWZhdWx0IHx8IHByZXZlbnREZWZhdWx0O1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbiA9IGUuc3RvcFByb3BhZ2F0aW9uIHx8IHN0b3BQcm9wYWdhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuLmNhbGwoZWxlbWVudCwgZSwgeCwgeSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBvYmouYXR0YWNoRXZlbnQoXCJvblwiICsgdHlwZSwgZik7XG4gICAgICAgICAgICAgICAgdmFyIGRldGFjaGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBvYmouZGV0YWNoRXZlbnQoXCJvblwiICsgdHlwZSwgZik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRldGFjaGVyO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0pKCksXG4gICAgZHJhZyA9IFtdLFxuICAgIGRyYWdNb3ZlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHggPSBlLmNsaWVudFgsXG4gICAgICAgICAgICB5ID0gZS5jbGllbnRZLFxuICAgICAgICAgICAgc2Nyb2xsWSA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgfHwgZy5kb2MuYm9keS5zY3JvbGxUb3AsXG4gICAgICAgICAgICBzY3JvbGxYID0gZy5kb2MuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnQgfHwgZy5kb2MuYm9keS5zY3JvbGxMZWZ0LFxuICAgICAgICAgICAgZHJhZ2ksXG4gICAgICAgICAgICBqID0gZHJhZy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChqLS0pIHtcbiAgICAgICAgICAgIGRyYWdpID0gZHJhZ1tqXTtcbiAgICAgICAgICAgIGlmIChzdXBwb3J0c1RvdWNoICYmIGUudG91Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpID0gZS50b3VjaGVzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgdG91Y2g7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgICAgICB0b3VjaCA9IGUudG91Y2hlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRvdWNoLmlkZW50aWZpZXIgPT0gZHJhZ2kuZWwuX2RyYWcuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSB0b3VjaC5jbGllbnRYO1xuICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHRvdWNoLmNsaWVudFk7XG4gICAgICAgICAgICAgICAgICAgICAgICAoZS5vcmlnaW5hbEV2ZW50ID8gZS5vcmlnaW5hbEV2ZW50IDogZSkucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2Y
57590XIgbm9kZSA9IGRyYWdpLmVsLm5vZGUsXG4gICAgICAgICAgICAgICAgbyxcbiAgICAgICAgICAgICAgICBuZXh0ID0gbm9kZS5uZXh0U2libGluZyxcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBub2RlLnBhcmVudE5vZGUsXG4gICAgICAgICAgICAgICAgZGlzcGxheSA9IG5vZGUuc3R5bGUuZGlzcGxheTtcbiAgICAgICAgICAgIGcud2luLm9wZXJhICYmIHBhcmVudC5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgIG5vZGUuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgbyA9IGRyYWdpLmVsLnBhcGVyLmdldEVsZW1lbnRCeVBvaW50KHgsIHkpO1xuICAgICAgICAgICAgbm9kZS5zdHlsZS5kaXNwbGF5ID0gZGlzcGxheTtcbiAgICAgICAgICAgIGcud2luLm9wZXJhICYmIChuZXh0ID8gcGFyZW50Lmluc2VydEJlZm9yZShub2RlLCBuZXh0KSA6IHBhcmVudC5hcHBlbmRDaGlsZChub2RlKSk7XG4gICAgICAgICAgICBvICYmIGV2ZShcInJhcGhhZWwuZHJhZy5vdmVyLlwiICsgZHJhZ2kuZWwuaWQsIGRyYWdpLmVsLCBvKTtcbiAgICAgICAgICAgIHggKz0gc2Nyb2xsWDtcbiAgICAgICAgICAgIHkgKz0gc2Nyb2xsWTtcbiAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuZHJhZy5tb3ZlLlwiICsgZHJhZ2kuZWwuaWQsIGRyYWdpLm1vdmVfc2NvcGUgfHwgZHJhZ2kuZWwsIHggLSBkcmFnaS5lbC5fZHJhZy54LCB5IC0gZHJhZ2kuZWwuX2RyYWcueSwgeCwgeSwgZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRyYWdVcCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIFIudW5tb3VzZW1vdmUoZHJhZ01vdmUpLnVubW91c2V1cChkcmFnVXApO1xuICAgICAgICB2Y
57590XIgaSA9IGRyYWcubGVuZ3RoLFxuICAgICAgICAgICAgZHJhZ2k7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGRyYWdpID0gZHJhZ1tpXTtcbiAgICAgICAgICAgIGRyYWdpLmVsLl9kcmFnID0ge307XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmRyYWcuZW5kLlwiICsgZHJhZ2kuZWwuaWQsIGRyYWdpLmVuZF9zY29wZSB8fCBkcmFnaS5zdGFydF9zY29wZSB8fCBkcmFnaS5tb3ZlX3Njb3BlIHx8IGRyYWdpLmVsLCBlKTtcbiAgICAgICAgfVxuICAgICAgICBkcmFnID0gW107XG4gICAgfSxcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5lbFxuICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgKipcbiAgICAgKiBZb3UgY2FuIGFkZCB5b3VyIG93biBtZXRob2QgdG8gZWxlbWVudHMuIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IHdhbnQgdG8gaGFjayBkZWZhdWx0IGZ1bmN0aW9uYWxpdHkgb3JcbiAgICAgKiB3YW50IHRvIHdyYXAgc29tZSBjb21tb24gdHJhbnNmb3JtYXRpb24gb3IgYXR0cmlidXRlcyBpbiBvbmUgbWV0aG9kLiBJbiBkaWZmZXJlbmNlIHRvIGNhbnZhcyBtZXRob2RzLFxuICAgICAqIHlvdSBjYW4gcmVkZWZpbmUgZWxlbWVudCBtZXRob2QgYXQgYW55IHRpbWUuIEV4cGVuZGluZyBlbGVtZW50IG1ldGhvZHMgd291bGRu4oCZdCBhZmZlY3Qgc2V0LlxuICAgICA+IFVzYWdlXG4gICAgIHwgUmFwaGFlbC5lbC5yZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgIHwgICAgIHRoaXMuYXR0cih7ZmlsbDogXCIjZjAwXCJ9KTtcbiAgICAgfCB9O1xuICAgICB8IC8vIHRoZW4gdXNlIGl0XG4gICAgI
57590HwgcGFwZXIuY2lyY2xlKDEwMCwgMTAwLCAyMCkucmVkKCk7XG4gICAgXFwqL1xuICAgIGVscHJvdG8gPSBSLmVsID0ge307XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuY2xpY2tcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgY2xpY2sgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5jbGlja1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBjbGljayBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG5cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5kYmxjbGlja1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVyIGZvciBkb3VibGUgY2xpY2sgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5kYmxjbGlja1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBkb3VibGUgY2xpY2sgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQubW91c2Vkb3duXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNlZG93biBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC51bm1vdXNlZG93blxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBtb3VzZWRvd24gZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQubW91c2Vtb3ZlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNlbW92ZSBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC51bm1vdXNlbW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBtb3VzZW1vdmUgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQubW91c2VvdXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgbW91c2VvdXQgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5tb3VzZW91dFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBtb3VzZW91dCBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG5cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5tb3VzZW92ZXJcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgbW91c2VvdmVyIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVubW91c2VvdmVyXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNlb3ZlciBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG5cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5tb3VzZXVwXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNldXAgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5tb3VzZXVwXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNldXAgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudG91Y2hzdGFydFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaHN0YXJ0IGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVudG91Y2hzdGFydFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaHN0YXJ0IGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pICNvcHRpb25hbCBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cblxuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnRvdWNobW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaG1vdmUgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW50b3VjaG1vdmVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlciBmb3IgdG91Y2htb3ZlIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pICNvcHRpb25hbCBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cblxuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnRvdWNoZW5kXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIHRvdWNoZW5kIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVudG91Y2hlbmRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlciBmb3IgdG91Y2hlbmQgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudG91Y2hjYW5jZWxcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgdG91Y2hjYW5jZWwgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW50b3VjaGNhbmNlbFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaGNhbmNlbCBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgZm9yICh2YXIgaSA9IGV2ZW50cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgKGZ1bmN0aW9uIChldmVudE5hbWUpIHtcbiAgICAgICAgICAgIFJbZXZlbnROYW1lXSA9IGVscHJvdG9bZXZlbnROYW1lXSA9IGZ1bmN0aW9uIChmbiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoUi5pcyhmbiwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50cyA9IHRoaXMuZXZlbnRzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50cy5wdXNoKHtuYW1lOiBldmVudE5hbWUsIGY6IGZuLCB1bmJpbmQ6IGFkZEV2ZW50KHRoaXMuc2hhcGUgfHwgdGhpcy5ub2RlIHx8IGcuZG9jLCBldmVudE5hbWUsIGZuLCBzY29wZSB8fCB0aGlzKX0pO1xuICAgICAgICAgICAgICAgI
57590H1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBSW1widW5cIiArIGV2ZW50TmFtZV0gPSBlbHByb3RvW1widW5cIiArIGV2ZW50TmFtZV0gPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5ldmVudHMgfHwgW10sXG4gICAgICAgICAgICAgICAgICAgIGwgPSBldmVudHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHdoaWxlIChsLS0pe1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnRzW2xdLm5hbWUgPT0gZXZlbnROYW1lICYmIChSLmlzKGZuLCBcInVuZGVmaW5lZFwiKSB8fCBldmVudHNbbF0uZiA9PSBmbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c1tsXS51bmJpbmQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zcGxpY2UobCwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAhZXZlbnRzLmxlbmd0aCAmJiBkZWxldGUgdGhpcy5ldmVudHM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KShldmVudHNbaV0pO1xuICAgIH1cblxuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LmRhdGFcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgb3IgcmV0cmlldmVzIGdpdmVuIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCBnaXZlbiBrZXkuXG4gICAgICoqXG4gICAgICogU2VlIGFsc28gQEVsZW1lbnQucmVtb3ZlRGF0YVxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBrZXkgKHN0cmluZykga2V5IHRvIHN0b3JlIGRhdGFcbiAgICAgLSB2YWx1ZSAoYW55KSAjb3B0aW9uYWwgdmFsdWUgdG8gc3RvcmVcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgICAqIG9yLCBpZiB2YWx1ZSBpcyBub3Qgc3BlY2lmaWVkOlxuICAgICA9IChhbnkpIHZhbHVlXG4gICAgICogb3IsIGlmIGtleSBhbmQgdmFsdWUgYXJlIG5vdCBzcGVjaWZpZWQ6XG4gICAgID0gKG9iamVjdCkgS2V5L3ZhbHVlIHBhaXJzIGZvciBhbGwgdGhlIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBlbGVtZW50LlxuICAgICA+IFVzYWdlXG4gICAgIHwgZm9yICh2YXIgaSA9IDAsIGkgPCA1LCBpKyspIHtcbiAgICAgfCAgICAgcGFwZXIuY2lyY2xlKDEwICsgMTUgKiBpLCAxMCwgMTApXG4gICAgIHwgICAgICAgICAgLmF0dHIoe2ZpbGw6IFwiIzAwMFwifSlcbiAgICAgfCAgICAgICAgICAuZGF0YShcImlcIiwgaSlcbiAgICAgfCAgICAgICAgICAuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICB8ICAgICAgICAgICAgIGFsZXJ0KHRoaXMuZGF0YShcImlcIikpO1xuICAgICB8ICAgICAgICAgIH0pO1xuICAgICB8IH1cbiAgICBcXCovXG4gICAgZWxwcm90by5kYXRhID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBlbGRhdGFbdGhpcy5pZF0gPSBlbGRhdGFbdGhpcy5pZF0gfHwge307XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgIGlmIChSLmlzKGtleSwgXCJvYmplY3RcIikpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIGtleSkgaWYgKGtleVtoYXNdKGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YShpLCBrZXlbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuZGF0YS5nZXQuXCIgKyB0aGlzLmlkLCB0aGlzLCBkYXRhW2tleV0sIGtleSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YVtrZXldO1xuICAgICAgICB9XG4gICAgICAgIGRhdGFba2V5XSA9IHZhbHVlO1xuICAgICAgICBldmUoXCJyYXBoYWVsLmRhdGEuc2V0LlwiICsgdGhpcy5pZCwgdGhpcywgdmFsdWUsIGtleSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQucmVtb3ZlRGF0YVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggYW4gZWxlbWVudCBieSBnaXZlbiBrZXkuXG4gICAgICogSWYga2V5IGlzIG5vdCBwcm92aWRlZCwgcmVtb3ZlcyBhbGwgdGhlIGRhdGEgb2YgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGtleSAoc3RyaW5nKSAjb3B0aW9uYWwga2V5XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgZWxwcm90by5yZW1vdmVEYXRhID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09IG51bGwpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBlbGRhdGFbdGhpcy5pZF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGRhdGFbdGhpcy5pZF0gJiYgZGVsZXRlIGVsZGF0YVt0aGlzLmlkXVtrZXldO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LmdldERhdGFcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHJpZXZlcyB0aGUgZWxlbWVudCBkYXRhXG4gICAgID0gKG9iamVjdCkgZGF0YVxuICAgIFxcKi9cbiAgICBlbHByb3RvLmdldERhdGEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBjbG9uZShlbGRhdGFbdGhpcy5pZF0gfHwge30pO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuaG92ZXJcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlcnMgZm9yIGhvdmVyIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gZl9pbiAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGhvdmVyIGluXG4gICAgIC0gZl9vdXQgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciBob3ZlciBvdXRcbiAgICAgLSBpY29udGV4dCAob2JqZWN0KSAjb3B0aW9uYWwgY29udGV4dCBmb3IgaG92ZXIgaW4gaGFuZGxlclxuICAgICAtIG9jb250ZXh0IChvYmplY3QpICNvcHRpb25hbCBjb250ZXh0IGZvciBob3ZlciBvdXQgaGFuZGxlclxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaG92ZXIgPSBmdW5jdGlvbiAoZl9pbiwgZl9vdXQsIHNjb3BlX2luLCBzY29wZV9vdXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW91c2VvdmVyKGZfaW4sIHNjb3BlX2luKS5tb3VzZW91dChmX291dCwgc2NvcGVfb3V0IHx8IHNjb3BlX2luKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVuaG92ZXJcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlcnMgZm9yIGhvdmVyIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gZl9pbiAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGhvdmVyIGluXG4gICAgIC0gZl9vdXQgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciBob3ZlciBvdXRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnVuaG92ZXIgPSBmdW5jdGlvbiAoZl9pbiwgZl9vdXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudW5tb3VzZW92ZXIoZl9pbikudW5tb3VzZW91dChmX291dCk7XG4gICAgfTtcbiAgICB2YXIgZ
57590HJhZ2dhYmxlID0gW107XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuZHJhZ1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVycyBmb3IgZHJhZyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gb25tb3ZlIChmdW5jdGlvbikgaGFuZGxlciBmb3IgbW92aW5nXG4gICAgIC0gb25zdGFydCAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGRyYWcgc3RhcnRcbiAgICAgLSBvbmVuZCAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGRyYWcgZW5kXG4gICAgIC0gbWNvbnRleHQgKG9iamVjdCkgI29wdGlvbmFsIGNvbnRleHQgZm9yIG1vdmluZyBoYW5kbGVyXG4gICAgIC0gc2NvbnRleHQgKG9iamVjdCkgI29wdGlvbmFsIGNvbnRleHQgZm9yIGRyYWcgc3RhcnQgaGFuZGxlclxuICAgICAtIGVjb250ZXh0IChvYmplY3QpICNvcHRpb25hbCBjb250ZXh0IGZvciBkcmFnIGVuZCBoYW5kbGVyXG4gICAgICogQWRkaXRpb25hbGx5IGZvbGxvd2luZyBgZHJhZ2AgZXZlbnRzIHdpbGwgYmUgdHJpZ2dlcmVkOiBgZHJhZy5zdGFydC48aWQ+YCBvbiBzdGFydCxcbiAgICAgKiBgZHJhZy5lbmQuPGlkPmAgb24gZW5kIGFuZCBgZHJhZy5tb3ZlLjxpZD5gIG9uIGV2ZXJ5IG1vdmUuIFdoZW4gZWxlbWVudCB3aWxsIGJlIGRyYWdnZWQgb3ZlciBhbm90aGVyIGVsZW1lbnRcbiAgICAgKiBgZHJhZy5vdmVyLjxpZD5gIHdpbGwgYmUgZmlyZWQgYXMgd2VsbC5cbiAgICAgKlxuICAgICAqIFN0YXJ0IGV2ZW50IGFuZCBzdGFydCBoYW5kbGVyIHdpbGwgYmUgY2FsbGVkIGluIHNwZWNpZmllZCBjb250ZXh0IG9yIGluIGNvbnRleHQgb2YgdGhlIGVsZW1lbnQgd2l0aCBmb2xsb3dpbmcgcGFyYW1ldGVyczpcbiAgICAgbyB4IChudW1iZXIpIHggcG9zaXRpb24gb2YgdGhlIG1vdXNlXG4gICAgIG8geSAobnVtYmVyKSB5IHBvc2l0aW9uIG9mIHRoZSBtb3VzZVxuICAgICBvIGV2ZW50IChvYmplY3QpIERPTSBldmVudCBvYmplY3RcbiAgICAgKiBNb3ZlIGV2ZW50IGFuZCBtb3ZlIGhhbmRsZXIgd2lsbCBiZSBjYWxsZWQgaW4gc3BlY2lmaWVkIGNvbnRleHQgb3IgaW4gY29udGV4dCBvZiB0aGUgZWxlbWVudCB3aXRoIGZvbGxvd2luZyBwYXJhbWV0ZXJzOlxuICAgICBvIGR4IChudW1iZXIpIHNoaWZ0IGJ5IHggZnJvbSB0aGUgc3RhcnQgcG9pbnRcbiAgICAgbyBkeSAobnVtYmVyKSBzaGlmdCBieSB5IGZyb20gdGhlIHN0YXJ0IHBvaW50XG4gICAgIG8geCAobnVtYmVyKSB4IHBvc2l0aW9uIG9mIHRoZSBtb3VzZVxuICAgICBvIHkgKG51bWJlcikgeSBwb3NpdGlvbiBvZiB0aGUgbW91c2VcbiAgICAgbyBldmVudCAob2JqZWN0KSBET00gZXZlbnQgb2JqZWN0XG4gICAgICogRW5kIGV2ZW50IGFuZCBlbmQgaGFuZGxlciB3aWxsIGJlIGNhbGxlZCBpbiBzcGVjaWZpZWQgY29udGV4dCBvciBpbiBjb250ZXh0IG9mIHRoZSBlbGVtZW50IHdpdGggZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gICAgIG8gZXZlbnQgKG9iamVjdCkgRE9NIGV2ZW50IG9iamVjdFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uZHJhZyA9IGZ1bmN0aW9uIChvbm1vdmUsIG9uc3RhcnQsIG9uZW5kLCBtb3ZlX3Njb3BlLCBzdGFydF9zY29wZSwgZW5kX3Njb3BlKSB7XG4gICAgICAgIGZ1bmN0aW9uIHN0YXJ0KGUpIHtcbiAgICAgICAgICAgIChlLm9yaWdpbmFsRXZlbnQgfHwgZSkucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHZhciB4ID0gZS5jbGllbnRYLFxuICAgICAgICAgICAgICAgIHkgPSBlLmNsaWVudFksXG4gICAgICAgICAgICAgICAgc2Nyb2xsWSA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgfHwgZy5kb2MuYm9keS5zY3JvbGxUb3AsXG4gICAgICAgICAgICAgICAgc2Nyb2xsWCA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGcuZG9jLmJvZHkuc2Nyb2xsTGVmdDtcbiAgICAgICAgICAgIHRoaXMuX2RyYWcuaWQgPSBlLmlkZW50aWZpZXI7XG4gICAgICAgICAgICBpZiAoc3VwcG9ydHNUb3VjaCAmJiBlLnRvdWNoZXMpIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgaSA9IGUudG91Y2hlcy5sZW5ndGgsIHRvdWNoO1xuICAgICAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgdG91Y2ggPSBlLnRvdWNoZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RyYWcuaWQgPSB0b3VjaC5pZGVudGlmaWVyO1xuICAgICAgICAgICAgICAgICAgICBpZiAodG91Y2guaWRlbnRpZmllciA9PSB0aGlzLl9kcmFnLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4ID0gdG91Y2guY2xpZW50WDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSB0b3VjaC5jbGllbnRZO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9kcmFnLnggPSB4ICsgc2Nyb2xsWDtcbiAgICAgICAgICAgIHRoaXMuX2RyYWcueSA9IHkgKyBzY3JvbGxZO1xuICAgICAgICAgICAgIWRyYWcubGVuZ3RoICYmIFIubW91c2Vtb3ZlKGRyYWdNb3ZlKS5tb3VzZXVwKGRyYWdVcCk7XG4gICAgICAgICAgICBkcmFnLnB1c2goe2VsOiB0aGlzLCBtb3ZlX3Njb3BlOiBtb3ZlX3Njb3BlLCBzdGFydF9zY29wZTogc3RhcnRfc2NvcGUsIGVuZF9zY29wZTogZW5kX3Njb3BlfSk7XG4gICAgICAgICAgICBvbnN0YXJ0ICYmIGV2ZS5vbihcInJhcGhhZWwuZHJhZy5zdGFydC5cIiArIHRoaXMuaWQsIG9uc3RhcnQpO1xuICAgICAgICAgICAgb25tb3ZlICYmIGV2ZS5vbihcInJhcGhhZWwuZHJhZy5tb3ZlLlwiICsgdGhpcy5pZCwgb25tb3ZlKTtcbiAgICAgICAgICAgIG9uZW5kICYmIGV2ZS5vbihcInJhcGhhZWwuZHJhZy5lbmQuXCIgKyB0aGlzLmlkLCBvbmVuZCk7XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmRyYWcuc3RhcnQuXCIgKyB0aGlzLmlkLCBzdGFydF9zY29wZSB8fCBtb3ZlX3Njb3BlIHx8IHRoaXMsIHR
57590oaXMuX2RyYWcueCwgdGhpcy5fZHJhZy55LCBlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9kcmFnID0ge307XG4gICAgICAgIGRyYWdnYWJsZS5wdXNoKHtlbDogdGhpcywgc3RhcnQ6IHN0YXJ0fSk7XG4gICAgICAgIHRoaXMubW91c2Vkb3duKHN0YXJ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5vbkRyYWdPdmVyXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBTaG9ydGN1dCBmb3IgYXNzaWduaW5nIGV2ZW50IGhhbmRsZXIgZm9yIGBkcmFnLm92ZXIuPGlkPmAgZXZlbnQsIHdoZXJlIGlkIGlzIGlkIG9mIHRoZSBlbGVtZW50IChzZWUgQEVsZW1lbnQuaWQpLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBmIChmdW5jdGlvbikgaGFuZGxlciBmb3IgZXZlbnQsIGZpcnN0IGFyZ3VtZW50IHdvdWxkIGJlIHRoZSBlbGVtZW50IHlvdSBhcmUgZHJhZ2dpbmcgb3ZlclxuICAgIFxcKi9cbiAgICBlbHByb3RvLm9uRHJhZ092ZXIgPSBmdW5jdGlvbiAoZikge1xuICAgICAgICBmID8gZXZlLm9uKFwicmFwaGFlbC5kcmFnLm92ZXIuXCIgKyB0aGlzLmlkLCBmKSA6IGV2ZS51bmJpbmQoXCJyYXBoYWVsLmRyYWcub3Zlci5cIiArIHRoaXMuaWQpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5kcmFnXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGFsbCBkcmFnIGV2ZW50IGhhbmRsZXJzIGZyb20gZ2l2ZW4gZWxlbWVudC5cbiAgICBcXCovXG4gICAgZWxwcm90by51bmRyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpID0gZHJhZ2dhYmxlLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkgaWYgKGRyYWdnYWJsZVtpXS5lbCA9PSB0aGlzKSB7XG4gICAgICAgICAgICB0aGlzLnVubW91c2Vkb3duKGRyYWdnYWJsZVtpXS5zdGFydCk7XG4gICAgICAgICAgICBkcmFnZ2FibGUuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgZXZlLnVuYmluZChcInJhcGhhZWwuZHJhZy4qLlwiICsgdGhpcy5pZCk7XG4gICAgICAgIH1cbiAgICAgICAgIWRyYWdnYWJsZS5sZW5ndGggJiYgUi51bm1vdXNlbW92ZShkcmFnTW92ZSkudW5tb3VzZXVwKGRyYWdVcCk7XG4gICAgICAgIGRyYWcgPSBbXTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5jaXJjbGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERyYXdzIGEgY2lyY2xlLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgY2VudHJlXG4gICAgIC0geSAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGNlbnRyZVxuICAgICAtIHIgKG51bWJlcikgcmFkaXVzXG4gICAgID0gKG9iamVjdCkgUmFwaGHDq2wgZWxlbWVudCBvYmplY3Qgd2l0aCB0eXBlIOKAnGNpcmNsZeKAnVxuICAgICAqKlxuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIGMgPSBwYXBlci5jaXJjbGUoNTAsIDUwLCA0MCk7XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uY2lyY2xlID0gZnVuY3Rpb24gKHgsIHksIHIpIHtcbiAgICAgICAgdmFyIG91dCA9IFIuX2VuZ2luZS5jaXJjbGUodGhpcywgeCB8fCAwLCB5IHx8IDAsIHIgfHwgMCk7XG4gICAgICAgIHRoaXMuX19zZXRfXyAmJiB0aGlzLl9fc2V0X18ucHVzaChvdXQpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnJlY3RcbiAgICAgWyBtZXRob2QgXVxuICAgICAqXG4gICAgICogRHJhd3MgYSByZWN0YW5nbGUuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIHggKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSB0b3AgbGVmdCBjb3JuZXJcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wIGxlZnQgY29ybmVyXG4gICAgIC0gd2lkdGggKG51bWJlcikgd2lkdGhcbiAgICAgLSBoZWlnaHQgKG51bWJlcikgaGVpZ2h0XG4gICAgIC0gciAobnVtYmVyKSAjb3B0aW9uYWwgcmFkaXVzIGZvciByb3VuZGVkIGNvcm5lcnMsIGRlZmF1bHQgaXMgMFxuICAgICA9IChvYmplY3QpIFJhcGhhw6tsIGVsZW1lbnQgb2JqZWN0IHdpdGggdHlwZSDigJxyZWN04oCdXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCAvLyByZWd1bGFyIHJlY3RhbmdsZVxuICAgICB8IHZhciBjID0gcGFwZXIucmVjdCgxMCwgMTAsIDUwLCA1MCk7XG4gICAgI
57590HwgLy8gcmVjdGFuZ2xlIHdpdGggcm91bmRlZCBjb3JuZXJzXG4gICAgIHwgdmFyIGMgPSBwYXBlci5yZWN0KDQwLCA0MCwgNTAsIDUwLCAxMCk7XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8ucmVjdCA9IGZ1bmN0aW9uICh4LCB5LCB3LCBoLCByKSB7XG4gICAgICAgIHZhciBvdXQgPSBSLl9lbmdpbmUucmVjdCh0aGlzLCB4IHx8IDAsIHkgfHwgMCwgdyB8fCAwLCBoIHx8IDAsIHIgfHwgMCk7XG4gICAgICAgIHRoaXMuX19zZXRfXyAmJiB0aGlzLl9fc2V0X18ucHVzaChvdXQpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmVsbGlwc2VcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERyYXdzIGFuIGVsbGlwc2UuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIHggKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBjZW50cmVcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgY2VudHJlXG4gICAgIC0gcnggKG51bWJlcikgaG9yaXpvbnRhbCByYWRpdXNcbiAgICAgLSByeSAobnVtYmVyKSB2ZXJ0aWNhbCByYWRpdXNcbiAgICAgPSAob2JqZWN0KSBSYXBoYcOrbCBlbGVtZW50IG9iamVjdCB3aXRoIHR5cGUg4oCcZWxsaXBzZeKAnVxuICAgICAqKlxuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIGMgPSBwYXBlci5lbGxpcHNlKDUwLCA1MCwgNDAsIDIwKTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5lbGxpcHNlID0gZnVuY3Rpb24gKHgsIHksIHJ4LCByeSkge1xuICAgICAgICB2Y
57590XIgb3V0ID0gUi5fZW5naW5lLmVsbGlwc2UodGhpcywgeCB8fCAwLCB5IHx8IDAsIHJ4IHx8IDAsIHJ5IHx8IDApO1xuICAgICAgICB0aGlzLl9fc2V0X18gJiYgdGhpcy5fX3NldF9fLnB1c2gob3V0KTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5wYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIGEgcGF0aCBlbGVtZW50IGJ5IGdpdmVuIHBhdGggZGF0YSBzdHJpbmcuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHBhdGhTdHJpbmcgKHN0cmluZykgI29wdGlvbmFsIHBhdGggc3RyaW5nIGluIFNWRyBmb3JtYXQuXG4gICAgICogUGF0aCBzdHJpbmcgY29uc2lzdHMgb2Ygb25lLWxldHRlciBjb21tYW5kcywgZm9sbG93ZWQgYnkgY29tbWEgc2VwcmFyYXRlZCBhcmd1bWVudHMgaW4gbnVtZXJjYWwgZm9ybS4gRXhhbXBsZTpcbiAgICAgfCBcIk0xMCwyMEwzMCw0MFwiXG4gICAgICogSGVyZSB3ZSBjYW4gc2VlIHR3byBjb21tYW5kczog4oCcTeKAnSwgd2l0aCBhcmd1bWVudHMgYCgxMCwgMjApYCBhbmQg4oCcTOKAnSB3aXRoIGFyZ3VtZW50cyBgKDMwLCA0MClgLiBVcHBlciBjYXNlIGxldHRlciBtZWFuIGNvbW1hbmQgaXMgYWJzb2x1dGUsIGxvd2VyIGNhc2XigJRyZWxhdGl2ZS5cbiAgICAgKlxuICAgICAjIDxwPkhlcmUgaXMgc2hvcnQgbGlzdCBvZiBjb21tYW5kcyBhdmFpbGFibGUsIGZvciBtb3JlIGRldGFpbHMgc2VlIDxhIGhyZWY9XCJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcvcGF0aHMuaHRtbCNQYXRoRGF0YVwiIHRpdGxlPVwiRGV0YWlscyBvZiBhIHBhdGgncyBkYXRhIGF0dHJpYnV0ZSdzIGZvcm1hdCBhcmUgZGVzY3JpYmVkIGluIHRoZSBTVkcgc3BlY2lmaWNhdGlvbi5cIj5TVkcgcGF0aCBzdHJpbmcgZm9ybWF0PC9hPi48L3A+XG4gICAgICMgPHRhYmxlPjx0aGVhZD48dHI+PHRoPkNvbW1hbmQ8L3RoPjx0aD5OYW1lPC90aD48dGg+UGFyYW1ldGVyczwvdGg+PC90cj48L3RoZWFkPjx0Ym9keT5cbiAgICAgIyA8dHI+PHRkPk08L3RkPjx0ZD5tb3ZldG88L3RkPjx0ZD4oeCB5KSs8L3RkPjwvdHI+XG4gICAgICMgPHRyPjx0ZD5aPC90ZD48dGQ+Y2xvc2VwYXRoPC90ZD48dGQ+KG5vbmUpPC90ZD48L3RyPlxuICAgICAjIDx0cj48dGQ+TDwvdGQ+PHRkPmxpbmV0bzwvdGQ+PHRkPih4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPkg8L3RkPjx0ZD5ob3Jpem9udGFsIGxpbmV0bzwvdGQ+PHRkPngrPC90ZD48L3RyPlxuICAgICAjIDx0cj48dGQ+VjwvdGQ+PHRkPnZlcnRpY2FsIGxpbmV0bzwvdGQ+PHRkPnkrPC90ZD48L3RyPlxuICAgICAjIDx0cj48dGQ+QzwvdGQ+PHRkPmN1cnZldG88L3RkPjx0ZD4oeDEgeTEgeDIgeTIgeCB5KSs8L3RkPjwvdHI+XG4gICAgICMgPHRyPjx0ZD5TPC90ZD48dGQ+c21vb3RoIGN1cnZldG88L3RkPjx0ZD4oeDIgeTIgeCB5KSs8L3RkPjwvdHI+XG4gICAgICMgPHRyPjx0ZD5RPC90ZD48dGQ+cXVhZHJhdGljIELDqXppZXIgY3VydmV0bzwvdGQ+PHRkPih4MSB5MSB4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPlQ8L3RkPjx0ZD5zbW9vdGggcXVhZHJhdGljIELDqXppZXIgY3VydmV0bzwvdGQ+PHRkPih4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPkE8L3RkPjx0ZD5lbGxpcHRpY2FsIGFyYzwvdGQ+PHRkPihyeCByeSB4LWF4aXMtcm90YXRpb24gbGFyZ2UtYXJjLWZsYWcgc3dlZXAtZmxhZyB4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPlI8L3RkPjx0ZD48YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DYXRtdWxs4oCTUm9tX3NwbGluZSNDYXRtdWxsLkUyLjgwLjkzUm9tX3NwbGluZVwiPkNhdG11bGwtUm9tIGN1cnZldG88L2E+KjwvdGQ+PHRkPngxIHkxICh4IHkpKzwvdGQ+PC90cj48L3Rib2R5PjwvdGFibGU+XG4gICAgICogKiDigJxDYXRtdWxsLVJvbSBjdXJ2ZXRv4oCdIGlzIGEgbm90IHN0YW5kYXJkIFNWRyBjb21tYW5kIGFuZCBhZGRlZCBpbiAyLjAgdG8gbWFrZSBsaWZlIGVhc2llci5cbiAgICAgKiBOb3RlOiB0aGVyZSBpcyBhIHNwZWNpYWwgY2FzZSB3aGVuIHBhdGggY29uc2lzdCBvZiBqdXN0IHRocmVlIGNvbW1hbmRzOiDigJxNMTAsMTBS4oCmeuKAnS4gSW4gdGhpcyBjYXNlIHBhdGggd2lsbCBzbW9vdGhseSBjb25uZWN0cyB0byBpdHMgYmVnaW5uaW5nLlxuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIGMgPSBwYXBlci5wYXRoKFwiTTEwIDEwTDkwIDkwXCIpO1xuICAgICB8IC8vIGRyYXcgYSBkaWFnb25hbCBsaW5lOlxuICAgICB8IC8vIG1vdmUgdG8gMTAsMTAsIGxpbmUgdG8gOTAsOTBcbiAgICAgKiBGb3IgZXhhbXBsZSBvZiBwYXRoIHN0cmluZ3MsIGNoZWNrIG91dCB0aGVzZSBpY29uczogaHR0cDovL3JhcGhhZWxqcy5jb20vaWNvbnMvXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8ucGF0aCA9IGZ1bmN0aW9uIChwYXRoU3RyaW5nKSB7XG4gICAgICAgIHBhdGhTdHJpbmcgJiYgIVIuaXMocGF0aFN0cmluZywgc3RyaW5nKSAmJiAhUi5pcyhwYXRoU3RyaW5nWzBdLCBhcnJheSkgJiYgKHBhdGhTdHJpbmcgKz0gRSk7XG4gICAgICAgIHZhciBvdXQgPSBSLl9lbmdpbmUucGF0aChSLmZvcm1hdFthcHBseV0oUiwgYXJndW1lbnRzKSwgdGhpcyk7XG4gICAgICAgIHRoaXMuX19zZXRfXyAmJiB0aGlzLl9fc2V0X18ucHVzaChvdXQpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmltYWdlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBFbWJlZHMgYW4gaW1hZ2UgaW50byB0aGUgc3VyZmFjZS5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gc3JjIChzdHJpbmcpIFVSSSBvZiB0aGUgc291cmNlIGltYWdlXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgcG9zaXRpb25cbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBwb3NpdGlvblxuICAgICAtIHdpZHRoIChudW1iZXIpIHdpZHRoIG9mIHRoZSBpbWFnZVxuICAgICAtIGhlaWdodCAobnVtYmVyKSBoZWlnaHQgb2YgdGhlIGltYWdlXG4gICAgID0gKG9iamVjdCkgUmFwaGHDq2wgZWxlbWVudCBvYmplY3Qgd2l0aCB0eXBlIOKAnGltYWdl4oCdXG4gICAgICoqXG4gICAgID4gVXNhZ2
57590VcbiAgICAgfCB2YXIgYyA9IHBhcGVyLmltYWdlKFwiYXBwbGUucG5nXCIsIDEwLCAxMCwgODAsIDgwKTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5pbWFnZSA9IGZ1bmN0aW9uIChzcmMsIHgsIHksIHcsIGgpIHtcbiAgICAgICAgdmFyIG91dCA9IFIuX2VuZ2luZS5pbWFnZSh0aGlzLCBzcmMgfHwgXCJhYm91dDpibGFua1wiLCB4IHx8IDAsIHkgfHwgMCwgdyB8fCAwLCBoIHx8IDApO1xuICAgICAgICB0aGlzLl9fc2V0X18gJiYgdGhpcy5fX3NldF9fLnB1c2gob3V0KTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci50ZXh0XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBEcmF3cyBhIHRleHQgc3RyaW5nLiBJZiB5b3UgbmVlZCBsaW5lIGJyZWFrcywgcHV0IOKAnFxcbuKAnSBpbiB0aGUgc3RyaW5nLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggY29vcmRpbmF0ZSBwb3NpdGlvblxuICAgICAtIHkgKG51bWJlcikgeSBjb29yZGluYXRlIHBvc2l0aW9uXG4gICAgIC0gdGV4dCAoc3RyaW5nKSBUaGUgdGV4dCBzdHJpbmcgdG8gZHJhd1xuICAgICA9IChvYmplY3QpIFJhcGhhw6tsIGVsZW1lbnQgb2JqZWN0IHdpdGggdHlwZSDigJx0ZXh04oCdXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCB2YXIgdCA9IHBhcGVyLnRleHQoNTAsIDUwLCBcIlJhcGhhw6tsXFxua2lja3NcXG5idXR0IVwiKTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by50ZXh0ID0gZnVuY3Rpb24gKHgsIHksIHRleHQpIHtcbiAgICAgICAgdmFyIG91dCA9IFIuX2VuZ2luZS50ZXh0KHRoaXMsIHggfHwgMCwgeSB8fCAwLCBTdHIodGV4dCkpO1xuICAgICAgICB0aGlzLl9fc2V0X18gJiYgdGhpcy5fX3NldF9fLnB1c2gob3V0KTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5zZXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgYXJyYXktbGlrZSBvYmplY3QgdG8ga2VlcCBhbmQgb3BlcmF0ZSBzZXZlcmFsIGVsZW1lbnRzIGF0IG9uY2UuXG4gICAgICogV2FybmluZzogaXQgZG9lc27igJl0IGNyZWF0ZSBhbnkgZWxlbWVudHMgZm9yIGl0c2VsZiBpbiB0aGUgcGFnZSwgaXQganVzdCBncm91cHMgZXhpc3RpbmcgZWxlbWVudHMuXG4gICAgICogU2V0cyBhY3QgYXMgcHNldWRvIGVsZW1lbnRzIOKAlCBhbGwgbWV0aG9kcyBhdmFpbGFibGUgdG8gYW4gZWxlbWVudCBjYW4gYmUgdXNlZCBvbiBhIHNldC5cbiAgICAgPSAob2JqZWN0KSBhcnJheS1saWtlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgc2V0IG9mIGVsZW1lbnRzXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCB2YXIgc3QgPSBwYXBlci5zZXQoKTtcbiAgICAgfCBzdC5wdXNoKFxuICAgICB8ICAgICBwYXBlci5jaXJjbGUoMTAsIDEwLCA1KSxcbiAgICAgfCAgICAgcGFwZXIuY2lyY2xlKDMwLCAxMCwgNSlcbiAgICAgfCApO1xuICAgICB8IHN0LmF0dHIoe2ZpbGw6IFwicmVkXCJ9KTsgLy8gY2hhbmdlcyB0aGUgZmlsbCBvZiBib3RoIGNpcmNsZXNcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5zZXQgPSBmdW5jdGlvbiAoaXRlbXNBcnJheSkge1xuICAgICAgICAhUi5pcyhpdGVtc0FycmF5LCBcImFycmF5XCIpICYmIChpdGVtc0FycmF5ID0gQXJyYXkucHJvdG90eXBlLnNwbGljZS5jYWxsKGFyZ3VtZW50cywgMCwgYXJndW1lbnRzLmxlbmd0aCkpO1xuICAgICAgICB2Y
57590XIgb3V0ID0gbmV3IFNldChpdGVtc0FycmF5KTtcbiAgICAgICAgdGhpcy5fX3NldF9fICYmIHRoaXMuX19zZXRfXy5wdXNoKG91dCk7XG4gICAgICAgIG91dFtcInBhcGVyXCJdID0gdGhpcztcbiAgICAgICAgb3V0W1widHlwZVwiXSA9IFwic2V0XCI7XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIuc2V0U3RhcnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgQFBhcGVyLnNldC4gQWxsIGVsZW1lbnRzIHRoYXQgd2lsbCBiZSBjcmVhdGVkIGFmdGVyIGNhbGxpbmcgdGhpcyBtZXRob2QgYW5kIGJlZm9yZSBjYWxsaW5nXG4gICAgICogQFBhcGVyLnNldEZpbmlzaCB3aWxsIGJlIGFkZGVkIHRvIHRoZSBzZXQuXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCBwYXBlci5zZXRTdGFydCgpO1xuICAgICB8IHBhcGVyLmNpcmNsZSgxMCwgMTAsIDUpLFxuICAgICB8IHBhcGVyLmNpcmNsZSgzMCwgMTAsIDUpXG4gICAgIHwgdmFyIHN0ID0gcGFwZXIuc2V0RmluaXNoKCk7XG4gICAgIHwgc3QuYXR0cih7ZmlsbDogXCJyZWRcIn0pOyAvLyBjaGFuZ2VzIHRoZSBmaWxsIG9mIGJvdGggY2lyY2xlc1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLnNldFN0YXJ0ID0gZnVuY3Rpb24gKHNldCkge1xuICAgICAgICB0aGlzLl9fc2V0X18gPSBzZXQgfHwgdGhpcy5zZXQoKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5zZXRGaW5pc2hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNlZSBAUGFwZXIuc2V0U3RhcnQuIFRoaXMgbWV0aG9kIGZpbmlzaGVzIGNhdGNoaW5nIGFuZCByZXR1cm5zIHJlc3VsdGluZyBzZXQuXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgc2V0XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uc2V0RmluaXNoID0gZnVuY3Rpb24gKHNldCkge1xuICAgICAgICB2Y
57590XIgb3V0ID0gdGhpcy5fX3NldF9fO1xuICAgICAgICBkZWxldGUgdGhpcy5fX3NldF9fO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmdldFNpemVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIE9idGFpbnMgY3VycmVudCBwYXBlciBhY3R1YWwgc2l6ZS5cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KVxuICAgICBcXCovXG4gICAgcGFwZXJwcm90by5nZXRTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5jYW52YXMucGFyZW50Tm9kZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdpZHRoOiBjb250YWluZXIub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IGNvbnRhaW5lci5vZmZzZXRIZWlnaHRcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5zZXRTaXplXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJZiB5b3UgbmVlZCB0byBjaGFuZ2UgZGltZW5zaW9ucyBvZiB0aGUgY2FudmFzIGNhbGwgdGhpcyBtZXRob2RcbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gd2lkdGggKG51bWJlcikgbmV3IHdpZHRoIG9mIHRoZSBjYW52YXNcbiAgICAgLSBoZWlnaHQgKG51bWJlcikgbmV3IGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uc2V0U2l6ZSA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBSLl9lbmdpbmUuc2V0U2l6ZS5jYWxsKHRoaXMsIHdpZHRoLCBoZWlnaHQpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnNldFZpZXdCb3hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNldHMgdGhlIHZpZXcgYm94IG9mIHRoZSBwYXBlci4gUHJhY3RpY2FsbHkgaXQgZ2l2ZXMgeW91IGFiaWxpdHkgdG8gem9vbSBhbmQgcGFuIHdob2xlIHBhcGVyIHN1cmZhY2UgYnlcbiAgICAgKiBzcGVjaWZ5aW5nIG5ldyBib3VuZGFyaWVzLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIG5ldyB4IHBvc2l0aW9uLCBkZWZhdWx0IGlzIGAwYFxuICAgICAtIHkgKG51bWJlcikgbmV3IHkgcG9zaXRpb24sIGRlZmF1bHQgaXMgYDBgXG4gICAgIC0gdyAobnVtYmVyKSBuZXcgd2lkdGggb2YgdGhlIGNhbnZhc1xuICAgICAtIGggKG51bWJlcikgbmV3IGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgIC0gZml0IChib29sZWFuKSBgdHJ1ZWAgaWYgeW91IHdhbnQgZ3JhcGhpY3MgdG8gZml0IGludG8gbmV3IGJvdW5kYXJ5IGJveFxuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLnNldFZpZXdCb3ggPSBmdW5jdGlvbiAoeCwgeSwgdywgaCwgZml0KSB7XG4gICAgICAgIHJldHVybiBSLl9lbmdpbmUuc2V0Vmlld0JveC5jYWxsKHRoaXMsIHgsIHksIHcsIGgsIGZpdCk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIudG9wXG4gICAgIFsgcHJvcGVydHkgXVxuICAgICAqKlxuICAgICAqIFBvaW50cyB0byB0aGUgdG9wbW9zdCBlbGVtZW50IG9uIHRoZSBwYXBlclxuICAgIFxcKi9cbiAgICAvKlxcXG4gICAgICogUGFwZXIuYm90dG9tXG4gICAgIFsgcHJvcGVydHkgXVxuICAgICAqKlxuICAgICAqIFBvaW50cyB0byB0aGUgYm90dG9tIGVsZW1lbnQgb24gdGhlIHBhcGVyXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8udG9wID0gcGFwZXJwcm90by5ib3R0b20gPSBudWxsO1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5yYXBoYWVsXG4gICAgIFsgcHJvcGVydHkgXVxuICAgICAqKlxuICAgICAqIFBvaW50cyB0byB0aGUgQFJhcGhhZWwgb2JqZWN0L2Z1bmN0aW9uXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8ucmFwaGFlbCA9IFI7XG4gICAgdmFyIGdldE9mZnNldCA9IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIHZhciBib3ggPSBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLFxuICAgICAgICAgICAgZG9jID0gZWxlbS5vd25lckRvY3VtZW50LFxuICAgICAgICAgICAgYm9keSA9IGRvYy5ib2R5LFxuICAgICAgICAgICAgZG9jRWxlbSA9IGRvYy5kb2N1bWVudEVsZW1lbnQsXG4gICAgICAgICAgICBjbGllbnRUb3AgPSBkb2NFbGVtLmNsaWVudFRvcCB8fCBib2R5LmNsaWVudFRvcCB8fCAwLCBjbGllbnRMZWZ0ID0gZG9jRWxlbS5jbGllbnRMZWZ0IHx8IGJvZHkuY2xpZW50TGVmdCB8fCAwLFxuICAgICAgICAgICAgdG9wICA9IGJveC50b3AgICsgKGcud2luLnBhZ2VZT2Zmc2V0IHx8IGRvY0VsZW0uc2Nyb2xsVG9wIHx8IGJvZHkuc2Nyb2xsVG9wICkgLSBjbGllbnRUb3AsXG4gICAgICAgICAgICBsZWZ0ID0gYm94LmxlZnQgKyAoZy53aW4ucGFnZVhPZmZzZXQgfHwgZG9jRWxlbS5zY3JvbGxMZWZ0IHx8IGJvZHkuc2Nyb2xsTGVmdCkgLSBjbGllbnRMZWZ0O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeTogdG9wLFxuICAgICAgICAgICAgeDogbGVmdFxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmdldEVsZW1lbnRCeVBvaW50XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHlvdSB0b3Btb3N0IGVsZW1lbnQgdW5kZXIgZ2l2ZW4gcG9pbnQuXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgUmFwaGHDq2wgZWxlbWVudCBvYmplY3RcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgZnJvbSB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSB3aW5kb3dcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBmcm9tIHRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgdGhlIHdpbmRvd1xuICAgICA+IFVzYWdlXG4gICAgIHwgcGFwZXIuZ2V0RWxlbWVudEJ5UG9pbnQobW91c2VYLCBtb3VzZVkpLmF0dHIoe3N0cm9rZTogXCIjZjAwXCJ9KTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5nZXRFbGVtZW50QnlQb2ludCA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIHZhciBwYXBlciA9IHRoaXMsXG4gICAgICAgICAgICBzdmcgPSBwYXBlci
575905jYW52YXMsXG4gICAgICAgICAgICB0YXJnZXQgPSBnLmRvYy5lbGVtZW50RnJvbVBvaW50KHgsIHkpO1xuICAgICAgICBpZiAoZy53aW4ub3BlcmEgJiYgdGFyZ2V0LnRhZ05hbWUgPT0gXCJzdmdcIikge1xuICAgICAgICAgICAgdmFyIHNvID0gZ2V0T2Zmc2V0KHN2ZyksXG4gICAgICAgICAgICAgICAgc3IgPSBzdmcuY3JlYXRlU1ZHUmVjdCgpO1xuICAgICAgICAgICAgc3IueCA9IHggLSBzby54O1xuICAgICAgICAgICAgc3IueSA9IHkgLSBzby55O1xuICAgICAgICAgICAgc3Iud2lkdGggPSBzci5oZWlnaHQgPSAxO1xuICAgICAgICAgICAgdmFyIGhpdHMgPSBzdmcuZ2V0SW50ZXJzZWN0aW9uTGlzdChzciwgbnVsbCk7XG4gICAgICAgICAgICBpZiAoaGl0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQgPSBoaXRzW2hpdHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICh0YXJnZXQucGFyZW50Tm9kZSAmJiB0YXJnZXQgIT0gc3ZnLnBhcmVudE5vZGUgJiYgIXRhcmdldC5yYXBoYWVsKSB7XG4gICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTtcbiAgICAgICAgfVxuICAgICAgICB0YXJnZXQgPT0gcGFwZXIuY2FudmFzLnBhcmVudE5vZGUgJiYgKHRhcmdldCA9IHN2Zyk7XG4gICAgICAgIHRhcmdldCA9IHRhcmdldCAmJiB0YXJnZXQucmFwaGFlbCA/IHBhcGVyLmdldEJ5SWQodGFyZ2V0LnJhcGhhZWxpZCkgOiBudWxsO1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUGFwZXIuZ2V0RWxlbWVudHNCeUJCb3hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgc2V0IG9mIGVsZW1lbnRzIHRoYXQgaGF2ZSBhbiBpbnRlcnNlY3RpbmcgYm91bmRpbmcgYm94XG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGJib3ggKG9iamVjdCkgYmJveCB0byBjaGVjayB3aXRoXG4gICAgID0gKG9iamVjdCkgQFNldFxuICAgICBcXCovXG4gICAgcGFwZXJwcm90by5nZXRFbGVtZW50c0J5QkJveCA9IGZ1bmN0aW9uIChiYm94KSB7XG4gICAgICAgIHZhciBzZXQgPSB0aGlzLnNldCgpO1xuICAgICAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBpZiAoUi5pc0JCb3hJbnRlcnNlY3QoZWwuZ2V0QkJveCgpLCBiYm94KSkge1xuICAgICAgICAgICAgICAgIHNldC5wdXNoKGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBzZXQ7XG4gICAgfTtcblxuICAgIC8qXFxcbiAgICAgKiBQYXBlci5nZXRCeUlkXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHlvdSBlbGVtZW50IGJ5IGl0cyBpbnRlcm5hbCBJRC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gaWQgKG51bWJlcikgaWRcbiAgICAgPSAob2JqZWN0KSBSYXBoYcOrbCBlbGVtZW50IG9iamVjdFxuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmdldEJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgdmFyIGJvdCA9IHRoaXMuYm90dG9tO1xuICAgICAgICB3aGlsZSAoYm90KSB7XG4gICAgICAgICAgICBpZiAoYm90LmlkID09IGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJvdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJvdCA9IGJvdC5uZXh0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmZvckVhY2hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEV4ZWN1dGVzIGdpdmVuIGZ1bmN0aW9uIGZvciBlYWNoIGVsZW1lbnQgb24gdGhlIHBhcGVyXG4gICAgICpcbiAgICAgKiBJZiBjYWxsYmFjayBmdW5jdGlvbiByZXR1cm5zIGBmYWxzZWAgaXQgd2lsbCBzdG9wIGxvb3AgcnVubmluZy5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gY2FsbGJhY2sgKGZ1bmN0aW9uKSBmdW5jdGlvbiB0byBydW5cbiAgICAgLSB0aGlzQXJnIChvYmplY3QpIGNvbnRleHQgb2JqZWN0IGZvciB0aGUgY2FsbGJhY2tcbiAgICAgPSAob2JqZWN0KSBQYXBlciBvYmplY3RcbiAgICAgPiBVc2FnZVxuICAgICB8IHBhcGVyLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgIHwgICAgIGVsLmF0dHIoeyBzdHJva2U6IFwiYmx1ZVwiIH0pO1xuICAgICB8IH0pO1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmZvckVhY2ggPSBmdW5jdGlvbiAoY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgICAgdmFyIGJvdCA9IHRoaXMuYm90dG9tO1xuICAgICAgICB3aGlsZSAoYm90KSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2suY2FsbCh0aGlzQXJnLCBib3QpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYm90ID0gYm90Lm5leHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIuZ2V0RWxlbWVudHNCeVBvaW50XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHNldCBvZiBlbGVtZW50cyB0aGF0IGhhdmUgY29tbW9uIHBvaW50IGluc2lkZVxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcbiAgICAgPSAob2JqZWN0KSBAU2V0XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uZ2V0RWxlbWVudHNCeVBvaW50ID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgdmFyIHNldCA9IHRoaXMuc2V0KCk7XG4gICAgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbC5pc1BvaW50SW5zaWRlKHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgc2V0LnB1c2goZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNldDtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHhfeSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueCArIFMgKyB0aGlzLnk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHhfeV93X2goKSB7XG4gICAgICAgI
57590HJldHVybiB0aGlzLnggKyBTICsgdGhpcy55ICsgUyArIHRoaXMud2lkdGggKyBcIiBcXHhkNyBcIiArIHRoaXMuaGVpZ2h0O1xuICAgIH1cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5pc1BvaW50SW5zaWRlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBEZXRlcm1pbmUgaWYgZ2l2ZW4gcG9pbnQgaXMgaW5zaWRlIHRoaXMgZWxlbWVudOKAmXMgc2hhcGVcbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgIC0geSAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCBpZiBwb2ludCBpbnNpZGUgdGhlIHNoYXBlXG4gICAgXFwqL1xuICAgIGVscHJvdG8uaXNQb2ludEluc2lkZSA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIHZhciBycCA9IHRoaXMucmVhbFBhdGggPSBnZXRQYXRoW3RoaXMudHlwZV0odGhpcyk7XG4gICAgICAgIGlmICh0aGlzLmF0dHIoJ3RyYW5zZm9ybScpICYmIHRoaXMuYXR0cigndHJhbnNmb3JtJykubGVuZ3RoKSB7XG4gICAgICAgICAgICBycCA9IFIudHJhbnNmb3JtUGF0aChycCwgdGhpcy5hdHRyKCd0cmFuc2Zvcm0nKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFIuaXNQb2ludEluc2lkZVBhdGgocnAsIHgsIHkpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuZ2V0QkJveFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmV0dXJuIGJvdW5kaW5nIGJveCBmb3IgYSBnaXZlbiBlbGVtZW50XG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGlzV2l0aG91dFRyYW5zZm9ybSAoYm9vbGVhbikgZmxhZywgYHRydWVgIGlmIHlvdSB3YW50IHRvIGhhdmUgYm91bmRpbmcgYm94IGJlZm9yZSB0cmFuc2Zvcm1hdGlvbnMuIERlZmF1bHQgaXMgYGZhbHNlYC5cbiAgICAgPSAob2JqZWN0KSBCb3VuZGluZyBib3ggb2JqZWN0OlxuICAgICBvIHtcbiAgICAgbyAgICAgeDogKG51bWJlcikgdG9wIGxlZnQgY29ybmVyIHhcbiAgICAgbyAgICAgeTogKG51bWJlcikgdG9wIGxlZnQgY29ybmVyIHlcbiAgICAgbyAgICAgeDI6IChudW1iZXIpIGJvdHRvbSByaWdodCBjb3JuZXIgeFxuICAgICBvICAgICB5MjogKG51bWJlcikgYm90dG9tIHJpZ2h0IGNvcm5lciB5XG4gICAgIG8gICAgIHdpZHRoOiAobnVtYmVyKSB3aWR0aFxuICAgICBvICAgICBoZWlnaHQ6IChudW1iZXIpIGhlaWdodFxuICAgICBvIH1cbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRCQm94ID0gZnVuY3Rpb24gKGlzV2l0aG91dFRyYW5zZm9ybSkge1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cbiAgICAgICAgdmFyIF8gPSB0aGlzLl87XG4gICAgICAgIGlmIChpc1dpdGhvdXRUcmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIGlmIChfLmRpcnR5IHx8ICFfLmJib3h3dCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVhbFBhdGggPSBnZXRQYXRoW3RoaXMudHlwZV0odGhpcyk7XG4gICAgICAgICAgICAgICAgXy5iYm94d3QgPSBwYXRoRGltZW5zaW9ucyh0aGlzLnJlYWxQYXRoKTtcbiAgICAgICAgICAgICAgICBfLmJib3h3dC50b1N0cmluZyA9IHhfeV93X2g7XG4gICAgICAgICAgICAgICAgXy5kaXJ0eSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gXy5iYm94d3Q7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF8uZGlydHkgfHwgXy5kaXJ0eVQgfHwgIV8uYmJveCkge1xuICAgICAgICAgICAgaWYgKF8uZGlydHkgfHwgIXRoaXMucmVhbFBhdGgpIHtcbiAgICAgICAgICAgICAgICBfLmJib3h3dCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsUGF0aCA9IGdldFBhdGhbdGhpcy50eXBlXSh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF8uYmJveCA9IHBhdGhEaW1lbnNpb25zKG1hcFBhdGgodGhpcy5yZWFsUGF0aCwgdGhpcy5tYXRyaXgpKTtcbiAgICAgICAgICAgIF8uYmJveC50b1N0cmluZyA9IHhfeV93X2g7XG4gICAgICAgICAgICBfLmRpcnR5ID0gXy5kaXJ0eVQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfLmJib3g7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5jbG9uZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgY2xvbmUgb2YgYSBnaXZlbiBlbGVtZW50XG4gICAgICoqXG4gICAgXFwqL1xuICAgIGVscHJvdG8uY2xvbmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvdXQgPSB0aGlzLnBhcGVyW3RoaXMudHlwZV0oKS5hdHRyKHRoaXMuYXR0cigpKTtcbiAgICAgICAgdGhpcy5fX3NldF9fICYmIHRoaXMuX19zZXRfXy5wdXNoKG91dCk7XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5nbG93XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm4gc2V0IG9mIGVsZW1lbnRzIHRoYXQgY3JlYXRlIGdsb3ctbGlrZSBlZmZlY3QgYXJvdW5kIGdpdmVuIGVsZW1lbnQuIFNlZSBAUGFwZXIuc2V0LlxuICAgICAqXG4gICAgICogTm90ZTogR2xvdyBpcyBub3QgY29ubmVjdGVkIHRvIHRoZSBlbGVtZW50LiBJZiB5b3UgY2hhbmdlIGVsZW1lbnQgYXR0cmlidXRlcyBpdCB3b27igJl0IGFkanVzdCBpdHNlbGYuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGdsb3cgKG9iamVjdCkgI29wdGlvbmFsIHBhcmFtZXRlcnMgb2JqZWN0IHdpdGggYWxsIHByb3BlcnRpZXMgb3B0aW9uYWw6XG4gICAgIG8ge1xuICAgICBvICAgICB3aWR0aCAobnVtYmVyKSBzaXplIG9mIHRoZSBnbG93LCBkZWZhdWx0IGlzIGAxMGBcbiAgICAgbyAgICAgZmlsbCAoYm9vbGVhbikgd2lsbCBpdCBiZSBmaWxsZWQsIGRlZmF1bHQgaXMgYGZhbHNlYFxuICAgICBvICAgICBvcGFjaXR5IChudW1iZXIpIG9wYWNpdHksIGRlZmF1bHQgaXMgYDAuNWBcbiAgICAgbyAgICAgb2Zmc2V0eCAobnVtYmVyKSBob3Jpem9udGFsIG9mZnNldCwgZGVmYXVsdCBpcyBgMGBcbiAgICAgbyAgICAgb2Zmc2V0eSAobnVtYmVyKSB2ZXJ0aWNhbCBvZmZzZXQsIGRlZmF1bHQgaXMgYDBgXG4gICAgIG8gICAgIGNvbG9yIChzdHJpbmcpIGdsb3cgY29sb3VyLCBkZWZhdWx0IGlzIGBibGFja2BcbiAgICAgbyB9XG4gICAgID0gKG9iamVjdCkgQFBhcGVyLnNldCBvZiBlbGVtZW50cyB0aGF0IHJlcHJlc2VudHMgZ2xvd1xuICAgIFxcKi9cbiAgICBlbHByb3RvLmdsb3cgPSBmdW5jdGlvbiAoZ2xvdykge1xuICAgICAgICBpZiAodGhpcy50eXBlID09IFwidGV4dFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBnbG93ID0gZ2xvdyB8fCB7fTtcbiAgICAgICAgdmFyIHMgPSB7XG4gICAgICAgICAgICB3aWR0aDogKGdsb3cud2lkdGggfHwgMTApICsgKCt0aGlzLmF0dHIoXCJzdHJva2Utd2lkdGhcIikgfHwgMSksXG4gICAgICAgICAgICBmaWxsOiBnbG93LmZpbGwgfHwgZmFsc2UsXG4gICAgICAgICAgICBvcGFjaXR5OiBnbG93Lm9wYWNpdHkgPT0gbnVsbCA/IC41IDogZ2xvdy5vcGFjaXR5LFxuICAgICAgICAgICAgb2Zmc2V0eDogZ2xvdy5vZmZzZXR4IHx8IDAsXG4gICAgICAgICAgICBvZmZzZXR5OiBnbG93Lm9mZnNldHkgfHwgMCxcbiAgICAgICAgICAgIGNvbG9yOiBnbG93Lm
57590NvbG9yIHx8IFwiIzAwMFwiXG4gICAgICAgIH0sXG4gICAgICAgICAgICBjID0gcy53aWR0aCAvIDIsXG4gICAgICAgICAgICByID0gdGhpcy5wYXBlcixcbiAgICAgICAgICAgIG91dCA9IHIuc2V0KCksXG4gICAgICAgICAgICBwYXRoID0gdGhpcy5yZWFsUGF0aCB8fCBnZXRQYXRoW3RoaXMudHlwZV0odGhpcyk7XG4gICAgICAgIHBhdGggPSB0aGlzLm1hdHJpeCA/IG1hcFBhdGgocGF0aCwgdGhpcy5tYXRyaXgpIDogcGF0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBjICsgMTsgaSsrKSB7XG4gICAgICAgICAgICBvdXQucHVzaChyLnBhdGgocGF0aCkuYXR0cih7XG4gICAgICAgICAgICAgICAgc3Ryb2tlOiBzLmNvbG9yLFxuICAgICAgICAgICAgICAgIGZpbGw6IHMuZmlsbCA/IHMuY29sb3IgOiBcIm5vbmVcIixcbiAgICAgICAgICAgICAgICBcInN0cm9rZS1saW5lam9pblwiOiBcInJvdW5kXCIsXG4gICAgICAgICAgICAgICAgXCJzdHJva2UtbGluZWNhcFwiOiBcInJvdW5kXCIsXG4gICAgICAgICAgICAgICAgXCJzdHJva2Utd2lkdGhcIjogKyhzLndpZHRoIC8gYyAqIGkpLnRvRml4ZWQoMyksXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogKyhzLm9wYWNpdHkgLyBjKS50b0ZpeGVkKDMpXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dC5pbnNlcnRCZWZvcmUodGhpcykudHJhbnNsYXRlKHMub2Zmc2V0eCwgcy5vZmZzZXR5KTtcbiAgICB9O1xuICAgIHZhciBjdXJ2ZXNsZW5ndGhzID0ge30sXG4gICAgZ2V0UG9pbnRBdFNlZ21lbnRMZW5ndGggPSBmdW5jdGlvbiAocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIGxlbmd0aCkge1xuICAgICAgICBpZiAobGVuZ3RoID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBiZXpsZW4ocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFIuZmluZERvdHNBdFNlZ21lbnQocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIGdldFRhdExlbihwMXgsIHAxeSwgYzF4LCBjMXksIGMyeCwgYzJ5LCBwMngsIHAyeSwgbGVuZ3RoKSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGdldExlbmd0aEZhY3RvcnkgPSBmdW5jdGlvbiAoaXN0b3RhbCwgc3VicGF0aCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHBhdGgsIGxlbmd0aCwgb25seXN0YXJ0KSB7XG4gICAgICAgICAgICBwYXRoID0gcGF0aDJjdXJ2ZShwYXRoKTtcbiAgICAgICAgICAgIHZhciB4LCB5LCBwLCBsLCBzcCA9IFwiXCIsIHN1YnBhdGhzID0ge30sIHBvaW50LFxuICAgICAgICAgICAgICAgIGxlbiA9IDA7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBwYXRoLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwID0gcGF0aFtpXTtcbiAgICAgICAgICAgICAgICBpZiAocFswXSA9PSBcIk1cIikge1xuICAgICAgICAgICAgICAgICAgICB4ID0gK3BbMV07XG4gICAgICAgICAgICAgICAgICAgIHkgPSArcFsyXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsID0gZ2V0UG9pbnRBdFNlZ21lbnRMZW5ndGgoeCwgeSwgcFsxXSwgcFsyXSwgcFszXSwgcFs0XSwgcFs1XSwgcFs2XSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZW4gKyBsID4gbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3VicGF0aCAmJiAhc3VicGF0aHMuc3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludCA9IGdldFBvaW50QXRTZWdtZW50TGVuZ3RoKHgsIHksIHBbMV0sIHBbMl0sIHBbM10sIHBbNF0sIHBbNV0sIHBbNl0sIGxlbmd0aCAtIGxlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3AgKz0gW1wiQ1wiICsgcG9pbnQuc3RhcnQueCwgcG9pbnQuc3RhcnQueSwgcG9pbnQubS54LCBwb2ludC5tLnksIHBvaW50LngsIHBvaW50LnldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvbmx5c3RhcnQpIHtyZXR1cm4gc3A7fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnBhdGhzLnN0YXJ0ID0gc3A7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3AgPSBbXCJNXCIgKyBwb2ludC54LCBwb2ludC55ICsgXCJDXCIgKyBwb2ludC5uLngsIHBvaW50Lm4ueSwgcG9pbnQuZW5kLngsIHBvaW50LmVuZC55LCBwWzVdLCBwWzZdXS5qb2luKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuICs9IGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICtwWzVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSArcFs2XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXN0b3RhbCAmJiAhc3VicGF0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ID0gZ2V0UG9pbnRBdFNlZ21lbnRMZW5ndGgoeCwgeSwgcFsxXSwgcFsyXSwgcFszXSwgcFs0XSwgcFs1XSwgcFs2XSwgbGVuZ3RoIC0gbGVuKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge3g6IHBvaW50LngsIHk6IHBvaW50LnksIGFscGhhOiBwb2ludC5hbHBoYX07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGVuICs9IGw7XG4gICAgICAgICAgICAgICAgICAgIHggPSArcFs1XTtcbiAgICAgICAgICAgICAgICAgICAgeSA9ICtwWzZdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzcCArPSBwLnNoaWZ0KCkgKyBwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3VicGF0aHMuZW5kID0gc3A7XG4gICAgICAgICAgICBwb2ludCA9IGlzdG90YWwgPyBsZW4gOiBzdWJwYXRoID8gc3VicGF0aHMgOiBSLmZpbmREb3RzQXRTZWdtZW50KHgsIHksIHBbMF0sIHBbMV0sIHBbMl0sIHBbM10sIHBbNF0sIHBbNV0sIDEpO1xuICAgICAgICAgICAgcG9pbnQuYWxwaGEgJiYgKHBvaW50ID0ge3g6IHBvaW50LngsIHk6IHBvaW50LnksIGFscGhhOiBwb2ludC5hbHBoYX0pO1xuICAgICAgICAgICAgcmV0dXJuIHBvaW50O1xuICAgICAgICB9O1xuICAgIH07XG4gICAgdmFyIGdldFRvdGFsTGVuZ3RoID0gZ2V0TGVuZ3RoRmFjdG9yeSgxKSxcbiAgICAgICAgZ2V0UG9pbnRBdExlbmd0aCA9IGdldExlbmd0aEZhY3RvcnkoKSxcbiAgICAgICAgZ2V0U3VicGF0aHNBdExlbmd0aCA9IGdldExlbmd0aEZhY3RvcnkoMCwgMSk7XG4gICAgLypcXFxuICAgICAqIFJhcGh
57590hZWwuZ2V0VG90YWxMZW5ndGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgbGVuZ3RoIG9mIHRoZSBnaXZlbiBwYXRoIGluIHBpeGVscy5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gcGF0aCAoc3RyaW5nKSBTVkcgcGF0aCBzdHJpbmcuXG4gICAgICoqXG4gICAgID0gKG51bWJlcikgbGVuZ3RoLlxuICAgIFxcKi9cbiAgICBSLmdldFRvdGFsTGVuZ3RoID0gZ2V0VG90YWxMZW5ndGg7XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuZ2V0UG9pbnRBdExlbmd0aFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmV0dXJuIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBsb2NhdGVkIGF0IHRoZSBnaXZlbiBsZW5ndGggb24gdGhlIGdpdmVuIHBhdGguXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIHBhdGggKHN0cmluZykgU1ZHIHBhdGggc3RyaW5nXG4gICAgIC0gbGVuZ3RoIChudW1iZXIpXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50OlxuICAgICBvIHtcbiAgICAgbyAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlXG4gICAgIG8gICAgIHk6IChudW1iZXIpIHkgY29vcmRpbmF0ZVxuICAgICBvICAgICBhbHBoYTogKG51bWJlcikgYW5nbGUgb2YgZGVyaXZhdGl2ZVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5nZXRQb2ludEF0TGVuZ3RoID0gZ2V0UG9pbnRBdExlbmd0aDtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5nZXRTdWJwYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm4gc3VicGF0aCBvZiBhIGdpdmVuIHBhdGggZnJvbSBnaXZlbiBsZW5ndGggdG8gZ2l2ZW4gbGVuZ3RoLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBwYXRoIChzdHJpbmcpIFNWRyBwYXRoIHN0cmluZ1xuICAgICAtIGZyb20gKG51bWJlcikgcG9zaXRpb24gb2YgdGhlIHN0YXJ0IG9mIHRoZSBzZWdtZW50XG4gICAgIC0gdG8gKG51bWJlcikgcG9zaXRpb24gb2YgdGhlIGVuZCBvZiB0aGUgc2VnbWVudFxuICAgICAqKlxuICAgICA9IChzdHJpbmcpIHBhdGhzdHJpbmcgZm9yIHRoZSBzZWdtZW50XG4gICAgXFwqL1xuICAgIFIuZ2V0U3VicGF0aCA9IGZ1bmN0aW9uIChwYXRoLCBmcm9tLCB0bykge1xuICAgICAgICBpZiAodGhpcy5nZXRUb3RhbExlbmd0aChwYXRoKSAtIHRvIDwgMWUtNikge1xuICAgICAgICAgICAgcmV0dXJuIGdldFN1YnBhdGhzQXRMZW5ndGgocGF0aCwgZnJvbSkuZW5kO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhID0gZ2V0U3VicGF0aHNBdExlbmd0aChwYXRoLCB0bywgMSk7XG4gICAgICAgIHJldHVybiBmcm9tID8gZ2V0U3VicGF0aHNBdExlbmd0aChhLCBmcm9tKS5lbmQgOiBhO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuZ2V0VG90YWxMZW5ndGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgbGVuZ3RoIG9mIHRoZSBwYXRoIGluIHBpeGVscy4gT25seSB3b3JrcyBmb3IgZWxlbWVudCBvZiDigJxwYXRo4oCdIHR5cGUuXG4gICAgID0gKG51bWJlcikgbGVuZ3RoLlxuICAgIFxcKi9cbiAgICBlbHByb3RvLmdldFRvdGFsTGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2Y
57590XIgcGF0aCA9IHRoaXMuZ2V0UGF0aCgpO1xuICAgICAgICBpZiAoIXBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm5vZGUuZ2V0VG90YWxMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5vZGUuZ2V0VG90YWxMZW5ndGgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBnZXRUb3RhbExlbmd0aChwYXRoKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LmdldFBvaW50QXRMZW5ndGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybiBjb29yZGluYXRlcyBvZiB0aGUgcG9pbnQgbG9jYXRlZCBhdCB0aGUgZ2l2ZW4gbGVuZ3RoIG9uIHRoZSBnaXZlbiBwYXRoLiBPbmx5IHdvcmtzIGZvciBlbGVtZW50IG9mIOKAnHBhdGjigJ0gdHlwZS5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gbGVuZ3RoIChudW1iZXIpXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50OlxuICAgICBvIHtcbiAgICAgbyAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlXG4gICAgIG8gICAgIHk6IChudW1iZXIpIHkgY29vcmRpbmF0ZVxuICAgICBvICAgICBhbHBoYTogKG51bWJlcikgYW5nbGUgb2YgZGVyaXZhdGl2ZVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRQb2ludEF0TGVuZ3RoID0gZnVuY3Rpb24gKGxlbmd0aCkge1xuICAgICAgICB2YXIgcGF0aCA9IHRoaXMuZ2V0UGF0aCgpO1xuICAgICAgICBpZiAoIXBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBnZXRQb2ludEF0TGVuZ3RoKHBhdGgsIGxlbmd0aCk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5nZXRQYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHBhdGggb2YgdGhlIGVsZW1lbnQuIE9ubHkgd29ya3MgZm9yIGVsZW1lbnRzIG9mIOKAnHBhdGjigJ0gdHlwZSBhbmQgc2ltcGxlIGVsZW1lbnRzIGxpa2UgY2lyY2xlLlxuICAgICA9IChvYmplY3QpIHBhdGhcbiAgICAgKipcbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRQYXRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2Y
57590XIgcGF0aCxcbiAgICAgICAgICAgIGdldFBhdGggPSBSLl9nZXRQYXRoW3RoaXMudHlwZV07XG5cbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PSBcInRleHRcIiB8fCB0aGlzLnR5cGUgPT0gXCJzZXRcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdldFBhdGgpIHtcbiAgICAgICAgICAgIHBhdGggPSBnZXRQYXRoKHRoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5nZXRTdWJwYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm4gc3VicGF0aCBvZiBhIGdpdmVuIGVsZW1lbnQgZnJvbSBnaXZlbiBsZW5ndGggdG8gZ2l2ZW4gbGVuZ3RoLiBPbmx5IHdvcmtzIGZvciBlbGVtZW50IG9mIOKAnHBhdGjigJ0gdHlwZS5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gZnJvbSAobnVtYmVyKSBwb3NpdGlvbiBvZiB0aGUgc3RhcnQgb2YgdGhlIHNlZ21lbnRcbiAgICAgLSB0byAobnVtYmVyKSBwb3NpdGlvbiBvZiB0aGUgZW5kIG9mIHRoZSBzZWdtZW50XG4gICAgICoqXG4gICAgID0gKHN0cmluZykgcGF0aHN0cmluZyBmb3IgdGhlIHNlZ21lbnRcbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRTdWJwYXRoID0gZnVuY3Rpb24gKGZyb20sIHRvKSB7XG4gICAgICAgIHZhciBwYXRoID0gdGhpcy5nZXRQYXRoKCk7XG4gICAgICAgIGlmICghcGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFIuZ2V0U3VicGF0aChwYXRoLCBmcm9tLCB0byk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5lYXNpbmdfZm9ybXVsYXNcbiAgICAgWyBwcm9wZXJ0eSBdXG4gICAgICoqXG4gICAgICogT2JqZWN0IHRoYXQgY29udGFpbnMgZWFzaW5nIGZvcm11bGFzIGZvciBhbmltYXRpb24uIFlvdSBjb3VsZCBleHRlbmQgaXQgd2l0aCB5b3VyIG93bi4gQnkgZGVmYXVsdCBpdCBoYXMgZm9sbG93aW5nIGxpc3Qgb2YgZWFzaW5nOlxuICAgICAjIDx1bD5cbiAgICAgIyAgICAgPGxpPuKAnGxpbmVhcuKAnTwvbGk+XG4gICAgICMgICAgIDxsaT7igJwmbHQ74oCdIG9yIOKAnGVhc2VJbuKAnSBvciDigJxlYXNlLWlu4oCdPC9saT5cbiAgICAgIyAgICAgPGxpPuKAnD7igJ0gb3Ig4oCcZWFzZU91dOKAnSBvciDigJxlYXNlLW91dOKAnTwvbGk+XG4gICAgICMgICAgIDxsaT7igJwmbHQ7PuKAnSBvciDigJxlYXNlSW5PdXTigJ0gb3Ig4oCcZWFzZS1pbi1vdXTigJ08L2xpPlxuICAgICAjICAgICA8bGk+4oCcYmFja0lu4oCdIG9yIOKAnGJhY2staW7igJ08L2xpPlxuICAgICAjICAgICA8bGk+4oCcYmFja091dOKAnSBvciDigJxiYWNrLW91dOKAnTwvbGk+XG4gICAgICMgICAgIDxsaT7igJxlbGFzdGlj4oCdPC9saT5cbiAgICAgIyAgICAgPGxpPuKAnGJvdW5jZeKAnTwvbGk+XG4gICAgICMgPC91bD5cbiAgICAgIyA8cD5TZWUgYWxzbyA8YSBocmVmPVwiaHR0cDovL3JhcGhhZWxqcy5jb20vZWFzaW5nLmh0bWxcIj5FYXNpbmcgZGVtbzwvYT4uPC9wPlxuICAgIFxcKi9cbiAgICB2YXIgZWYgPSBSLmVhc2luZ19mb3JtdWxhcyA9IHtcbiAgICAgICAgbGluZWFyOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIH0sXG4gICAgICAgIFwiPFwiOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgcmV0dXJuIHBvdyhuLCAxLjcpO1xuICAgICAgICB9LFxuICAgICAgICBcIj5cIjogZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHJldHVybiBwb3cobiwgLjQ4KTtcbiAgICAgICAgfSxcbiAgICAgICAgXCI8PlwiOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgdmFyIHEgPSAuNDggLSBuIC8gMS4wNCxcbiAgICAgICAgICAgICAgICBRID0gbWF0aC5zcXJ0KC4xNzM0ICsgcSAqIHEpLFxuICAgICAgICAgICAgICAgIHggPSBRIC0gcSxcbiAgICAgICAgICAgICAgICBYID0gcG93KGFicyh4KSwgMSAvIDMpICogKHggPCAwID8gLTEgOiAxKSxcbiAgICAgICAgICAgICAgICB5ID0gLVEgLSBxLFxuICAgICAgICAgICAgICAgIFkgPSBwb3coYWJzKHkpLCAxIC8gMykgKiAoeSA8IDAgPyAtMSA6IDEpLFxuICAgICAgICAgICAgICAgIHQgPSBYICsgWSArIC41O1xuICAgICAgICAgICAgcmV0dXJuICgxIC0gdCkgKiAzICogdCAqIHQgKyB0ICogdCAqIHQ7XG4gICAgICAgIH0sXG4gICAgICAgIGJhY2tJbjogZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHZhciBzID0gMS43MDE1ODtcbiAgICAgICAgICAgIHJldHVybiBuICogbiAqICgocyArIDEpICogbiAtIHMpO1xuICAgICAgICB9LFxuICAgICAgICBiYWNrT3V0OiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgbiA9IG4gLSAxO1xuICAgICAgICAgICAgdmFyIHMgPSAxLjcwMTU4O1xuICAgICAgICAgICAgcmV0dXJuIG4gKiBuICogKChzICsgMSkgKiBuICsgcykgKyAxO1xuICAgICAgICB9LFxuICAgICAgICBlbGFzdGljOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgaWYgKG4gPT0gISFuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcG93KDIsIC0xMCAqIG4pICogbWF0aC5zaW4oKG4gLSAuMDc1KSAqICgyICogUEkpIC8gLjMpICsgMTtcbiAgICAgICAgfSxcbiAgICAgICAgYm91bmNlOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgdmFyIHMgPSA3LjU2MjUsXG4gICAgICAgICAgICAgICAgcCA9IDIuNzUsXG4gICAgICAgICAgICAgICAgbDtcbiAgICAgICAgICAgIGlmIChuIDwgKDEgLyBwKSkge1xuICAgICAgICAgICAgICAgIGwgPSBzICogbiAqIG47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChuIDwgKDIgLyBwKSkge1xuICAgICAgICAgICAgICAgICAgICBuIC09ICgxLjUgLyBwKTtcbiAgICAgICAgICAgICAgICAgICAgbCA9IHMgKiBuICogbiArIC43NTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAobiA8ICgyLjUgLyBwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbiAtPSAoMi4yNSAvIHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgbCA9IHMgKiBuICogbiArIC45Mzc1O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbiAtPSAoMi42MjUgLyBwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGwgPSBzICogbiAqIG4gKyAuOTg0Mzc1O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGw7XG4gICAgICAgI
57590H1cbiAgICB9O1xuICAgIGVmLmVhc2VJbiA9IGVmW1wiZWFzZS1pblwiXSA9IGVmW1wiPFwiXTtcbiAgICBlZi5lYXNlT3V0ID0gZWZbXCJlYXNlLW91dFwiXSA9IGVmW1wiPlwiXTtcbiAgICBlZi5lYXNlSW5PdXQgPSBlZltcImVhc2UtaW4tb3V0XCJdID0gZWZbXCI8PlwiXTtcbiAgICBlZltcImJhY2staW5cIl0gPSBlZi5iYWNrSW47XG4gICAgZWZbXCJiYWNrLW91dFwiXSA9IGVmLmJhY2tPdXQ7XG5cbiAgICB2YXIgYW5pbWF0aW9uRWxlbWVudHMgPSBbXSxcbiAgICAgICAgcmVxdWVzdEFuaW1GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgICAgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5vUmVxdWVzdEFuaW1hdGlvbkZyYW1lICAgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZSAgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIDE2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgIGFuaW1hdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBOb3cgPSArbmV3IERhdGUsXG4gICAgICAgICAgICAgICAgbCA9IDA7XG4gICAgICAgICAgICBmb3IgKDsgbCA8IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGUgPSBhbmltYXRpb25FbGVtZW50c1tsXTtcbiAgICAgICAgICAgICAgICBpZiAoZS5lbC5yZW1vdmVkIHx8IGUucGF1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2Y
57590XIgdGltZSA9IE5vdyAtIGUuc3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIG1zID0gZS5tcyxcbiAgICAgICAgICAgICAgICAgICAgZWFzaW5nID0gZS5lYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBlLmZyb20sXG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPSBlLmRpZmYsXG4gICAgICAgICAgICAgICAgICAgIHRvID0gZS50byxcbiAgICAgICAgICAgICAgICAgICAgdCA9IGUudCxcbiAgICAgICAgICAgICAgICAgICAgdGhhdCA9IGUuZWwsXG4gICAgICAgICAgICAgICAgICAgIHNldCA9IHt9LFxuICAgICAgICAgICAgICAgICAgICBub3csXG4gICAgICAgICAgICAgICAgICAgIGluaXQgPSB7fSxcbiAgICAgICAgICAgICAgICAgICAga2V5O1xuICAgICAgICAgICAgICAgIGlmIChlLmluaXRzdGF0dXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZSA9IChlLmluaXRzdGF0dXMgKiBlLmFuaW0udG9wIC0gZS5wcmV2KSAvIChlLnBlcmNlbnQgLSBlLnByZXYpICogbXM7XG4gICAgICAgICAgICAgICAgICAgIGUuc3RhdHVzID0gZS5pbml0c3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZS5pbml0c3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3AgJiYgYW5pbWF0aW9uRWxlbWVudHMuc3BsaWNlKGwtLSwgMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZS5zdGF0dXMgPSAoZS5wcmV2ICsgKGUucGVyY2VudCAtIGUucHJldikgKiAodGltZSAvIG1zKSkgLyBlLmFuaW0udG9wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGltZSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aW1lIDwgbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGVhc2luZyh0aW1lIC8gbXMpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyIGluIGZyb20pIGlmIChmcm9tW2hhc10oYXR0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXZhaWxhYmxlQW5pbUF0dHJzW2F0dHJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBudTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID0gK2Zyb21bYXR0cl0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjb2xvdXJcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID0gXCJyZ2IoXCIgKyBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHRvMjU1KHJvdW5kKGZyb21bYXR0cl0uciArIHBvcyAqIG1zICogZGlmZlthdHRyXS5yKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHRvMjU1KHJvdW5kKGZyb21bYXR0cl0uZyArIHBvcyAqIG1zICogZGlmZlthdHRyXS5nKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHRvMjU1KHJvdW5kKGZyb21bYXR0cl0uYiArIHBvcyAqIG1zICogZGlmZlthdHRyXS5iKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXS5qb2luKFwiLFwiKSArIFwiKVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3cgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZnJvbVthdHRyXS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV0gPSBbZnJvbVthdHRyXVtpXVswXV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMSwgamogPSBmcm9tW2F0dHJdW2ldLmxlbmd0aDsgaiA8IGpqOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV1bal0gPSArZnJvbVthdHRyXVtpXVtqXSArIHBvcyAqIG1zICogZGlmZlthdHRyXVtpXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vd1tpXSA9IG5vd1tpXS5qb2luKFMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IG5vdy5qb2luKFMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwidHJhbnNmb3JtXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkaWZmW2F0dHJdLnJlYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBmcm9tW2F0dHJdLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV0gPSBbZnJvbVthdHRyXVtpXVswXV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMSwgamogPSBmcm9tW2F0dHJdW2ldLmxlbmd0aDsgaiA8IGpqOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93W2ldW2pdID0gZnJvbVthdHRyXVtpXVtqXSArIHBvcyAqIG1zICogZGlmZlthdHRyXVtpXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57590XIgZ2V0ID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gK2Zyb21bYXR0cl1baV0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm93ID0gW1tcInJcIiwgZ2V0KDIpLCAwLCAwXSwgW1widFwiLCBnZXQoMyksIGdldCg0KV0sIFtcInNcIiwgZ2V0KDApLCBnZXQoMSksIDAsIDBdXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IFtbXCJtXCIsIGdldCgwKSwgZ2V0KDEpLCBnZXQoMiksIGdldCgzKSwgZ2V0KDQpLCBnZXQoNSldXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3N2XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyID09IFwiY2xpcC1yZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaSA9IDQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93W2ldID0gK2Zyb21bYXR0cl1baV0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZyb20yID0gW11bY29uY2F0XShmcm9tW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkgPSB0aGF0LnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbYXR0cl0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV0gPSArZnJvbTJbaV0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRbYXR0cl0gPSBub3c7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhhdC5hdHRyKHNldCk7XG4gICAgICAgICAgICAgICAgICAgIChmdW5jdGlvbiAoaWQsIHRoYXQsIGFuaW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuYW5pbS5mcmFtZS5cIiArIGlkLCB0aGF0LCBhbmltKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KSh0aGF0LmlkLCB0aGF0LCBlLmFuaW0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIChmdW5jdGlvbihmLCBlbCwgYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmUoXCJyYXBoYWVsLmFuaW0uZnJhbWUuXCIgKyBlbC5pZCwgZWwsIGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuYW5pbS5maW5pc2guXCIgKyBlbC5pZCwgZWwsIGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFIuaXMoZiwgXCJmdW5jdGlvblwiKSAmJiBmLmNhbGwoZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pKGUuY2FsbGJhY2ssIHRoYXQsIGUuYW5pbSk7XG4gICAgICAgICAgICAgICAgICAgIHRoYXQuYXR0cih0byk7XG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkVsZW1lbnRzLnNwbGljZShsLS0sIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5yZXBlYXQgPiAxICYmICFlLm5leHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIHRvKSBpZiAodG9baGFzXShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdFtrZXldID0gZS50b3RhbE9yaWdpbltrZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZS5lbC5hdHRyKGluaXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVuQW5pbWF0aW9uKGUuYW5pbSwgZS5lbCwgZS5hbmltLnBlcmNlbnRzWzBdLCBudWxsLCBlLnRvdGFsT3JpZ2luLCBlLnJlcGVhdCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLm5leHQgJiYgIWUuc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVuQW5pbWF0aW9uKGUuYW5pbSwgZS5lbCwgZS5uZXh0LCBudWxsLCBlLnRvdGFsT3JpZ2luLCBlLnJlcGVhdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5sZW5ndGggJiYgcmVxdWVzdEFuaW1GcmFtZShhbmltYXRpb24pO1xuICAgICAgICB9LFxuICAgICAgICB1cHRvMjU1ID0gZnVuY3Rpb24gKGNvbG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sb3IgPiAyNTUgPyAyNTUgOiBjb2xvciA8IDAgPyAwIDogY29sb3I7XG4gICAgICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuYW5pbWF0ZVdpdGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFjdHMgc2ltaWxhciB0byBARWxlbWVudC5hbmltYXRlLCBidXQgZW5zdXJlIHRoYXQgZ2l2ZW4gYW5pbWF0aW9uIHJ1bnMgaW4gc3luYy
57590B3aXRoIGFub3RoZXIgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gZWwgKG9iamVjdCkgZWxlbWVudCB0byBzeW5jIHdpdGhcbiAgICAgLSBhbmltIChvYmplY3QpIGFuaW1hdGlvbiB0byBzeW5jIHdpdGhcbiAgICAgLSBwYXJhbXMgKG9iamVjdCkgI29wdGlvbmFsIGZpbmFsIGF0dHJpYnV0ZXMgZm9yIHRoZSBlbGVtZW50LCBzZWUgYWxzbyBARWxlbWVudC5hdHRyXG4gICAgIC0gbXMgKG51bWJlcikgI29wdGlvbmFsIG51bWJlciBvZiBtaWxsaXNlY29uZHMgZm9yIGFuaW1hdGlvbiB0byBydW5cbiAgICAgLSBlYXNpbmcgKHN0cmluZykgI29wdGlvbmFsIGVhc2luZyB0eXBlLiBBY2NlcHQgb24gb2YgQFJhcGhhZWwuZWFzaW5nX2Zvcm11bGFzIG9yIENTUyBmb3JtYXQ6IGBjdWJpYyYjeDIwMTA7YmV6aWVyKFhYLCYjMTYwO1hYLCYjMTYwO1hYLCYjMTYwO1hYKWBcbiAgICAgLSBjYWxsYmFjayAoZnVuY3Rpb24pICNvcHRpb25hbCBjYWxsYmFjayBmdW5jdGlvbi4gV2lsbCBiZSBjYWxsZWQgYXQgdGhlIGVuZCBvZiBhbmltYXRpb24uXG4gICAgICogb3JcbiAgICAgLSBlbGVtZW50IChvYmplY3QpIGVsZW1lbnQgdG8gc3luYyB3aXRoXG4gICAgIC0gYW5pbSAob2JqZWN0KSBhbmltYXRpb24gdG8gc3luYyB3aXRoXG4gICAgIC0gYW5pbWF0aW9uIChvYmplY3QpICNvcHRpb25hbCBhbmltYXRpb24gb2JqZWN0LCBzZWUgQFJhcGhhZWwuYW5pbWF0aW9uXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLmFuaW1hdGVXaXRoID0gZnVuY3Rpb24gKGVsLCBhbmltLCBwYXJhbXMsIG1zLCBlYXNpbmcsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcztcbiAgICAgICAgaWYgKGVsZW1lbnQucmVtb3ZlZCkge1xuICAgICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2suY2FsbChlbGVtZW50KTtcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIHZhciBhID0gcGFyYW1zIGluc3RhbmNlb2YgQW5pbWF0aW9uID8gcGFyYW1zIDogUi5hbmltYXRpb24ocGFyYW1zLCBtcywgZWFzaW5nLCBjYWxsYmFjayksXG4gICAgICAgICAgICB4LCB5O1xuICAgICAgICBydW5BbmltYXRpb24oYSwgZWxlbWVudCwgYS5wZXJjZW50c1swXSwgbnVsbCwgZWxlbWVudC5hdHRyKCkpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBhbmltYXRpb25FbGVtZW50cy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoYW5pbWF0aW9uRWxlbWVudHNbaV0uYW5pbSA9PSBhbmltICYmIGFuaW1hdGlvbkVsZW1lbnRzW2ldLmVsID09IGVsKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uRWxlbWVudHNbaWkgLSAxXS5zdGFydCA9IGFuaW1hdGlvbkVsZW1lbnRzW2ldLnN0YXJ0O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgICAgICAvL1xuICAgICAgICAvL1xuICAgICAgICAvLyB2YXIgYSA9IHBhcmFtcyA/IFIuYW5pbWF0aW9uKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spIDogYW5pbSxcbiAgICAgICAgLy8gICAgIHN0YXR1cyA9IGVsZW1lbnQuc3RhdHVzKGFuaW0pO1xuICAgICAgICAvLyByZXR1cm4gdGhpcy5hbmltYXRlKGEpLnN0YXR1cyhhLCBzdGF0dXMgKiBhbmltLm1zIC8gYS5tcyk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBDdWJpY0JlemllckF0VGltZSh0LCBwMXgsIHAxeSwgcDJ4LCBwMnksIGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBjeCA9IDMgKiBwMXgsXG4gICAgICAgICAgICBieCA9IDMgKiAocDJ4IC0gcDF4KSAtIGN4LFxuICAgICAgICAgICAgYXggPSAxIC0gY3ggLSBieCxcbiAgICAgICAgICAgIGN5ID0gMyAqIHAxeSxcbiAgICAgICAgICAgIGJ5ID0gMyAqIChwMnkgLSBwMXkpIC0gY3ksXG4gICAgICAgICAgICBheSA9IDEgLSBjeSAtIGJ5O1xuICAgICAgICBmdW5jdGlvbiBzYW1wbGVDdXJ2ZVgodCkge1xuICAgICAgICAgICAgcmV0dXJuICgoYXggKiB0ICsgYngpICogdCArIGN4KSAqIHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gc29sdmUoeCwgZXBzaWxvbikge1xuICAgICAgICAgICAgdmFyIHQgPSBzb2x2ZUN1cnZlWCh4LCBlcHNpbG9uKTtcbiAgICAgICAgICAgIHJldHVybiAoKGF5ICogdCArIGJ5KSAqIHQgKyBjeSkgKiB0O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHNvbHZlQ3VydmVYKHgsIGVwc2lsb24pIHtcbiAgICAgICAgICAgIHZhciB0MCwgdDEsIHQyLCB4MiwgZDIsIGk7XG4gICAgICAgICAgICBmb3IodDIgPSB4LCBpID0gMDsgaSA8IDg7IGkrKykge1xuICAgICAgICAgICAgICAgIHgyID0gc2FtcGxlQ3VydmVYKHQyKSAtIHg7XG4gICAgICAgICAgICAgICAgaWYgKGFicyh4MikgPCBlcHNpbG9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0MjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZDIgPSAoMyAqIGF4ICogdDIgKyAyICogYngpICogdDIgKyBjeDtcbiAgICAgICAgICAgICAgICBpZiAoYWJzKGQyKSA8IDFlLTYpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHQyID0gdDIgLSB4MiAvIGQyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdDAgPSAwO1xuICAgICAgICAgICAgdDEgPSAxO1xuICAgICAgICAgICAgdDIgPSB4O1xuICAgICAgICAgICAgaWYgKHQyIDwgdDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodDIgPiB0MSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0MTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlICh0MCA8IHQxKSB7XG4gICAgICAgICAgICAgICAgeDIgPSBzYW1wbGVDdXJ2ZVgodDIpO1xuICAgICAgICAgICAgICAgIGlmIChhYnMoeDIgLSB4KSA8IGVwc2lsb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHQyO
575901xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeCA+IHgyKSB7XG4gICAgICAgICAgICAgICAgICAgIHQwID0gdDI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdDEgPSB0MjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdDIgPSAodDEgLSB0MCkgLyAyICsgdDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdDI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvbHZlKHQsIDEgLyAoMjAwICogZHVyYXRpb24pKTtcbiAgICB9XG4gICAgZWxwcm90by5vbkFuaW1hdGlvbiA9IGZ1bmN0aW9uIChmKSB7XG4gICAgICAgIGYgPyBldmUub24oXCJyYXBoYWVsLmFuaW0uZnJhbWUuXCIgKyB0aGlzLmlkLCBmKSA6IGV2ZS51bmJpbmQoXCJyYXBoYWVsLmFuaW0uZnJhbWUuXCIgKyB0aGlzLmlkKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBBbmltYXRpb24oYW5pbSwgbXMpIHtcbiAgICAgICAgdmFyIHBlcmNlbnRzID0gW10sXG4gICAgICAgICAgICBuZXdBbmltID0ge307XG4gICAgICAgIHRoaXMubXMgPSBtcztcbiAgICAgICAgdGhpcy50aW1lcyA9IDE7XG4gICAgICAgIGlmIChhbmltKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBhdHRyIGluIGFuaW0pIGlmIChhbmltW2hhc10oYXR0cikpIHtcbiAgICAgICAgICAgICAgICBuZXdBbmltW3RvRmxvYXQoYXR0cildID0gYW5pbVthdHRyXTtcbiAgICAgICAgICAgICAgICBwZXJjZW50cy5wdXNoKHRvRmxvYXQoYXR0cikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGVyY2VudHMuc29ydChzb3J0QnlOdW1iZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYW5pbSA9IG5ld0FuaW07XG4gICAgICAgIHRoaXMudG9wID0gcGVyY2VudHNbcGVyY2VudHMubGVuZ3RoIC0gMV07XG4gICAgICAgIHRoaXMucGVyY2VudHMgPSBwZXJjZW50cztcbiAgICB9XG4gICAgLypcXFxuICAgICAqIEFuaW1hdGlvbi5kZWxheVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ3JlYXRlcyBhIGNvcHkgb2YgZXhpc3RpbmcgYW5pbWF0aW9uIG9iamVjdCB3aXRoIGdpdmVuIGRlbGF5LlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBkZWxheSAobnVtYmVyKSBudW1iZXIgb2YgbXMgdG8gcGFzcyBiZXR3ZWVuIGFuaW1hdGlvbiBzdGFydCBhbmQgYWN0dWFsIGFuaW1hdGlvblxuICAgICAqKlxuICAgICA9IChvYmplY3QpIG5ldyBhbHRlcmVkIEFuaW1hdGlvbiBvYmplY3RcbiAgICAgfCB2YXIgYW5pbSA9IFJhcGhhZWwuYW5pbWF0aW9uKHtjeDogMTAsIGN5OiAyMH0sIDJlMyk7XG4gICAgI
57590HwgY2lyY2xlMS5hbmltYXRlKGFuaW0pOyAvLyBydW4gdGhlIGdpdmVuIGFuaW1hdGlvbiBpbW1lZGlhdGVseVxuICAgICB8IGNpcmNsZTIuYW5pbWF0ZShhbmltLmRlbGF5KDUwMCkpOyAvLyBydW4gdGhlIGdpdmVuIGFuaW1hdGlvbiBhZnRlciA1MDAgbXNcbiAgICBcXCovXG4gICAgQW5pbWF0aW9uLnByb3RvdHlwZS5kZWxheSA9IGZ1bmN0aW9uIChkZWxheSkge1xuICAgICAgICB2YXIgYSA9IG5ldyBBbmltYXRpb24odGhpcy5hbmltLCB0aGlzLm1zKTtcbiAgICAgICAgYS50aW1lcyA9IHRoaXMudGltZXM7XG4gICAgICAgIGEuZGVsID0gK2RlbGF5IHx8IDA7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEFuaW1hdGlvbi5yZXBlYXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgYSBjb3B5IG9mIGV4aXN0aW5nIGFuaW1hdGlvbiBvYmplY3Qgd2l0aCBnaXZlbiByZXBldGl0aW9uLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSByZXBlYXQgKG51bWJlcikgbnVtYmVyIGl0ZXJhdGlvbnMgb2YgYW5pbWF0aW9uLiBGb3IgaW5maW5pdGUgYW5pbWF0aW9uIHBhc3MgYEluZmluaXR5YFxuICAgICAqKlxuICAgICA9IChvYmplY3QpIG5ldyBhbHRlcmVkIEFuaW1hdGlvbiBvYmplY3RcbiAgICBcXCovXG4gICAgQW5pbWF0aW9uLnByb3RvdHlwZS5yZXBlYXQgPSBmdW5jdGlvbiAodGltZXMpIHtcbiAgICAgICAgdmFyIGEgPSBuZXcgQW5pbWF0aW9uKHRoaXMuYW5pbSwgdGhpcy5tcyk7XG4gICAgICAgIGEuZGVsID0gdGhpcy5kZWw7XG4gICAgICAgIGEudGltZXMgPSBtYXRoLmZsb29yKG1tYXgodGltZXMsIDApKSB8fCAxO1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHJ1bkFuaW1hdGlvbihhbmltLCBlbGVtZW50LCBwZXJjZW50LCBzdGF0dXMsIHRvdGFsT3JpZ2luLCB0aW1lcykge1xuICAgICAgICBwZXJjZW50ID0gdG9GbG9hdChwZXJjZW50KTtcbiAgICAgICAgdmFyIHBhcmFtcyxcbiAgICAgICAgICAgIGlzSW5BbmltLFxuICAgICAgICAgICAgaXNJbkFuaW1TZXQsXG4gICAgICAgICAgICBwZXJjZW50cyA9IFtdLFxuICAgICAgICAgICAgbmV4dCxcbiAgICAgICAgICAgIHByZXYsXG4gICAgICAgICAgICB0aW1lc3RhbXAsXG4gICAgICAgICAgICBtcyA9IGFuaW0ubXMsXG4gICAgICAgICAgICBmcm9tID0ge30sXG4gICAgICAgICAgICB0byA9IHt9LFxuICAgICAgICAgICAgZGlmZiA9IHt9O1xuICAgICAgICBpZiAoc3RhdHVzKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgZSA9IGFuaW1hdGlvbkVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgIGlmIChlLmVsLmlkID09IGVsZW1lbnQuaWQgJiYgZS5hbmltID09IGFuaW0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUucGVyY2VudCAhPSBwZXJjZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0luQW5pbVNldCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0luQW5pbSA9IGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hdHRyKGUudG90YWxPcmlnaW4pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0dXMgPSArdG87IC8vIE5hTlxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGFuaW0ucGVyY2VudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgaWYgKGFuaW0ucGVyY2VudHNbaV0gPT0gcGVyY2VudCB8fCBhbmltLnBlcmNlbnRzW2ldID4gc3RhdHVzICogYW5pbS50b3ApIHtcbiAgICAgICAgICAgICAgICBwZXJjZW50ID0gYW5pbS5wZXJjZW50c1tpXTtcbiAgICAgICAgICAgICAgICBwcmV2ID0gYW5pbS5wZXJjZW50c1tpIC0gMV0gfHwgMDtcbiAgICAgICAgICAgICAgICBtcyA9IG1zIC8gYW5pbS50b3AgKiAocGVyY2VudCAtIHByZXYpO1xuICAgICAgICAgICAgICAgIG5leHQgPSBhbmltLnBlcmNlbnRzW2kgKyAxXTtcbiAgICAgICAgICAgICAgICBwYXJhbXMgPSBhbmltLmFuaW1bcGVyY2VudF07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXR1cykge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXR0cihhbmltLmFuaW1bYW5pbS5wZXJjZW50c1tpXV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghcGFyYW1zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0luQW5pbSkge1xuICAgICAgICAgICAgZm9yICh2YXIgYXR0ciBpbiBwYXJhbXMpIGlmIChwYXJhbXNbaGFzXShhdHRyKSkge1xuICAgICAgICAgICAgICAgIGlmIChhdmFpbGFibGVBbmltQXR0cnNbaGFzXShhdHRyKSB8fCBlbGVtZW50LnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbaGFzXShhdHRyKSkge1xuICAgICAgICAgICAgICAgICAgICBmcm9tW2F0dHJdID0gZWxlbWVudC5hdHRyKGF0dHIpO1xuICAgICAgICAgICAgICAgICAgICAoZnJvbVthdHRyXSA9PSBudWxsKSAmJiAoZnJvbVthdHRyXSA9IGF2YWlsYWJsZUF0dHJzW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgdG9bYXR0cl0gPSBwYXJhbXNbYXR0cl07XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXZhaWxhYmxlQW5pbUF0dHJzW2F0dHJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIG51OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl0gPSAodG9bYXR0cl0gLSBmcm9tW2F0dHJdKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNvbG91clwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21bYXR0cl0gPSBSLmdldFJHQihmcm9tW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57590XIgdG9Db2xvdXIgPSBSLmdldFJHQih0b1thdHRyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcjogKHRvQ29sb3VyLnIgLSBmcm9tW2F0dHJdLnIpIC8gbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGc6ICh0b0NvbG91ci5nIC0gZnJvbVthdHRyXS5nKSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiOiAodG9Db2xvdXIuYiAtIGZyb21bYXR0cl0uYikgLyBtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYXRoZXMgPSBwYXRoMmN1cnZlKGZyb21bYXR0cl0sIHRvW2F0dHJdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9QYXRoID0gcGF0aGVzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21bYXR0cl0gPSBwYXRoZXNbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gZnJvbVthdHRyXS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl1baV0gPSBbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAxLCBqaiA9IGZyb21bYXR0cl1baV0ubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXVtpXVtqXSA9ICh0b1BhdGhbaV1bal0gLSBmcm9tW2F0dHJdW2ldW2pdKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInRyYW5zZm9ybVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfID0gZWxlbWVudC5fLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcSA9IGVxdWFsaXNlVHJhbnNmb3JtKF9bYXR0cl0sIHRvW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbVthdHRyXSA9IGVxLmZyb207XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvW2F0dHJdID0gZXEudG87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXS5yZWFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBmcm9tW2F0dHJdLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl1baV0gPSBbZnJvbVthdHRyXVtpXVswXV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAxLCBqaiA9IGZyb21bYXR0cl1baV0ubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl1baV1bal0gPSAodG9bYXR0cl1baV1bal0gLSBmcm9tW2F0dHJdW2ldW2pdKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG0gPSAoZWxlbWVudC5tYXRyaXggfHwgbmV3IE1hdHJpeCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bzIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXzoge3RyYW5zZm9ybTogXy50cmFuc2Zvcm19LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEJCb3g6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQuZ2V0QkJveCgxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tW2F0dHJdID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5hLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5iLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5jLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5kLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5mXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhY3RUcmFuc2Zvcm0odG8yLCB0b1thdHRyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvW2F0dHJdID0gdG8yLl8udHJhbnNmb3JtO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2F0dHJdID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRvMi5tYXRyaXguYSAtIG0uYSkgLyBtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0bzIubWF0cml4LmIgLSBtLmIpIC8gbX
57590MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodG8yLm1hdHJpeC5jIC0gbS5jKSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRvMi5tYXRyaXguZCAtIG0uZCkgLyBtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0bzIubWF0cml4LmUgLSBtLmUpIC8gbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodG8yLm1hdHJpeC5mIC0gbS5mKSAvIG1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZyb21bYXR0cl0gPSBbXy5zeCwgXy5zeSwgXy5kZWcsIF8uZHgsIF8uZHldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB2YXIgdG8yID0ge186e30sIGdldEJCb3g6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGVsZW1lbnQuZ2V0QkJveCgpOyB9fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXh0cmFjdFRyYW5zZm9ybSh0bzIsIHRvW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGlmZlthdHRyXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICh0bzIuXy5zeCAtIF8uc3gpIC8gbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICAodG8yLl8uc3kgLSBfLnN5KSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKHRvMi5fLmRlZyAtIF8uZGVnKSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKHRvMi5fLmR4IC0gXy5keCkgLyBtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICh0bzIuXy5keSAtIF8uZHkpIC8gbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3N2XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFN0cihwYXJhbXNbYXR0cl0pW3NwbGl0XShzZXBhcmF0b3IpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tMiA9IFN0cihmcm9tW2F0dHJdKVtzcGxpdF0oc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ciA9PSBcImNsaXAtcmVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21bYXR0cl0gPSBmcm9tMjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpID0gZnJvbTIubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2F0dHJdW2ldID0gKHZhbHVlc1tpXSAtIGZyb21bYXR0cl1baV0pIC8gbXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9bYXR0cl0gPSB2YWx1ZXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IFtdW2NvbmNhdF0ocGFyYW1zW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tMiA9IFtdW2NvbmNhdF0oZnJvbVthdHRyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkgPSBlbGVtZW50LnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbYXR0cl0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXVtpXSA9ICgodmFsdWVzW2ldIHx8IDApIC0gKGZyb20yW2ldIHx8IDApKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBlYXNpbmcgPSBwYXJhbXMuZWFzaW5nLFxuICAgICAgICAgICAgICAgIGVhc3llYXN5ID0gUi5lYXNpbmdfZm9ybXVsYXNbZWFzaW5nXTtcbiAgICAgICAgICAgIGlmICghZWFzeWVhc3kpIHtcbiAgICAgICAgICAgICAgICBlYXN5ZWFzeSA9IFN0cihlYXNpbmcpLm1hdGNoKGJlemllcnJnKTtcbiAgICAgICAgICAgICAgICBpZiAoZWFzeWVhc3kgJiYgZWFzeWVhc3kubGVuZ3RoID09IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnZlID0gZWFzeWVhc3k7XG4gICAgICAgICAgICAgICAgICAgIGVhc3llYXN5ID0gZnVuY3Rpb24gKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBDdWJpY0JlemllckF0VGltZSh0LCArY3VydmVbMV0sICtjdXJ2ZVsyXSwgK2N1cnZlWzNdLCArY3VydmVbNF0sIG1zKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlYXN5ZWFzeSA9IHBpcGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGltZXN0YW1wID0gcGFyYW1zLnN0YXJ0IHx8IGFuaW0uc3RhcnQgfHwgK25ldyBEYXRlO1xuICAgICAgICAgICAgZSA9IHtcbiAgICAgICAgICAgICAgICBhbmltOiBhbmltLFxuICAgICAgICAgICAgICAgIHBlcmNlbnQ6IHBlcmNlbnQsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiB0aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgc3RhcnQ6IHRpbWVzdGFtcCArIChhbmltLmRlbCB8fCAwKSxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IDAsXG4gICAgICAgICAgICAgICAgaW5pdHN0YXR1czogc3Rh
57590dHVzIHx8IDAsXG4gICAgICAgICAgICAgICAgc3RvcDogZmFsc2UsXG4gICAgICAgICAgICAgICAgbXM6IG1zLFxuICAgICAgICAgICAgICAgIGVhc2luZzogZWFzeWVhc3ksXG4gICAgICAgICAgICAgICAgZnJvbTogZnJvbSxcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHRvOiB0byxcbiAgICAgICAgICAgICAgICBlbDogZWxlbWVudCxcbiAgICAgICAgICAgICAgICBjYWxsYmFjazogcGFyYW1zLmNhbGxiYWNrLFxuICAgICAgICAgICAgICAgIHByZXY6IHByZXYsXG4gICAgICAgICAgICAgICAgbmV4dDogbmV4dCxcbiAgICAgICAgICAgICAgICByZXBlYXQ6IHRpbWVzIHx8IGFuaW0udGltZXMsXG4gICAgICAgICAgICAgICAgb3JpZ2luOiBlbGVtZW50LmF0dHIoKSxcbiAgICAgICAgICAgICAgICB0b3RhbE9yaWdpbjogdG90YWxPcmlnaW5cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5wdXNoKGUpO1xuICAgICAgICAgICAgaWYgKHN0YXR1cyAmJiAhaXNJbkFuaW0gJiYgIWlzSW5BbmltU2V0KSB7XG4gICAgICAgICAgICAgICAgZS5zdG9wID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBlLnN0YXJ0ID0gbmV3IERhdGUgLSBtcyAqIHN0YXR1cztcbiAgICAgICAgICAgICAgICBpZiAoYW5pbWF0aW9uRWxlbWVudHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFuaW1hdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0luQW5pbVNldCkge1xuICAgICAgICAgICAgICAgIGUuc3RhcnQgPSBuZXcgRGF0ZSAtIGUubXMgKiBzdGF0dXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5sZW5ndGggPT0gMSAmJiByZXF1ZXN0QW5pbUZyYW1lKGFuaW1hdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpc0luQW5pbS5pbml0c3RhdHVzID0gc3RhdHVzO1xuICAgICAgICAgICAgaXNJbkFuaW0uc3RhcnQgPSBuZXcgRGF0ZSAtIGlzSW5BbmltLm1zICogc3RhdHVzO1xuICAgICAgICB9XG4gICAgICAgIGV2ZShcInJhcGhhZWwuYW5pbS5zdGFydC5cIiArIGVsZW1lbnQuaWQsIGVsZW1lbnQsIGFuaW0pO1xuICAgIH1cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5hbmltYXRpb25cbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgYW4gYW5pbWF0aW9uIG9iamVjdCB0aGF0IGNhbiBiZSBwYXNzZWQgdG8gdGhlIEBFbGVtZW50LmFuaW1hdGUgb3IgQEVsZW1lbnQuYW5pbWF0ZVdpdGggbWV0aG9kcy5cbiAgICAgKiBTZWUgYWxzbyBAQW5pbWF0aW9uLmRlbGF5IGFuZCBAQW5pbWF0aW9uLnJlcGVhdCBtZXRob2RzLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBwYXJhbXMgKG9iamVjdCkgZmluYWwgYXR0cmlidXRlcyBmb3IgdGhlIGVsZW1lbnQsIHNlZSBhbHNvIEBFbGVtZW50LmF0dHJcbiAgICAgLSBtcyAobnVtYmVyKSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGZvciBhbmltYXRpb24gdG8gcnVuXG4gICAgIC0gZWFzaW5nIChzdHJpbmcpICNvcHRpb25hbCBlYXNpbmcgdHlwZS4gQWNjZXB0IG9uZSBvZiBAUmFwaGFlbC5lYXNpbmdfZm9ybXVsYXMgb3IgQ1NTIGZvcm1hdDogYGN1YmljJiN4MjAxMDtiZXppZXIoWFgsJiMxNjA7WFgsJiMxNjA7WFgsJiMxNjA7WFgpYFxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uLiBXaWxsIGJlIGNhbGxlZCBhdCB0aGUgZW5kIG9mIGFuaW1hdGlvbi5cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KSBAQW5pbWF0aW9uXG4gICAgXFwqL1xuICAgIFIuYW5pbWF0aW9uID0gZnVuY3Rpb24gKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHBhcmFtcyBpbnN0YW5jZW9mIEFuaW1hdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICAgICAgfVxuICAgICAgICBpZiAoUi5pcyhlYXNpbmcsIFwiZnVuY3Rpb25cIikgfHwgIWVhc2luZykge1xuICAgICAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayB8fCBlYXNpbmcgfHwgbnVsbDtcbiAgICAgICAgICAgIGVhc2luZyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcGFyYW1zID0gT2JqZWN0KHBhcmFtcyk7XG4gICAgICAgIG1zID0gK21zIHx8IDA7XG4gICAgICAgIHZhciBwID0ge30sXG4gICAgICAgICAgICBqc29uLFxuICAgICAgICAgICAgYXR0cjtcbiAgICAgICAgZm9yIChhdHRyIGluIHBhcmFtcykgaWYgKHBhcmFtc1toYXNdKGF0dHIpICYmIHRvRmxvYXQoYXR0cikgIT0gYXR0ciAmJiB0b0Zsb2F0KGF0dHIpICsgXCIlXCIgIT0gYXR0cikge1xuICAgICAgICAgICAganNvbiA9IHRydWU7XG4gICAgICAgICAgICBwW2F0dHJdID0gcGFyYW1zW2F0dHJdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghanNvbikge1xuICAgICAgICAgICAgLy8gaWYgcGVyY2VudC1saWtlIHN5bnRheCBpcyB1c2VkIGFuZCBlbmQtb2YtYWxsIGFuaW1hdGlvbiBjYWxsYmFjayB1c2VkXG4gICAgICAgICAgICBpZihjYWxsYmFjayl7XG4gICAgICAgICAgICAgICAgLy8gZmluZCB0aGUgbGFzdCBvbmVcbiAgICAgICAgICAgICAgICB2Y
57590XIgbGFzdEtleSA9IDA7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpIGluIHBhcmFtcyl7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwZXJjZW50ID0gdG9JbnQoaSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHBhcmFtc1toYXNdKGkpICYmIHBlcmNlbnQgPiBsYXN0S2V5KXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RLZXkgPSBwZXJjZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxhc3RLZXkgKz0gJyUnO1xuICAgICAgICAgICAgICAgIC8vIGlmIGFscmVhZHkgZGVmaW5lZCBjYWxsYmFjayBpbiB0aGUgbGFzdCBrZXlmcmFtZSwgc2tpcFxuICAgICAgICAgICAgICAgICFwYXJhbXNbbGFzdEtleV0uY2FsbGJhY2sgJiYgKHBhcmFtc1tsYXN0S2V5XS5jYWxsYmFjayA9IGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IEFuaW1hdGlvbihwYXJhbXMsIG1zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVhc2luZyAmJiAocC5lYXNpbmcgPSBlYXNpbmcpO1xuICAgICAgICAgICAgY2FsbGJhY2sgJiYgKHAuY2FsbGJhY2sgPSBjYWxsYmFjayk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEFuaW1hdGlvbih7MTAwOiBwfSwgbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5hbmltYXRlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIGFuZCBzdGFydHMgYW5pbWF0aW9uIGZvciBnaXZlbiBlbGVtZW50LlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBwYXJhbXMgKG9iamVjdCkgZmluYWwgYXR0cmlidXRlcyBmb3IgdGhlIGVsZW1lbnQsIHNlZSBhbHNvIEBFbGVtZW50LmF0dHJcbiAgICAgLSBtcyAobnVtYmVyKSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGZvciBhbmltYXRpb24gdG8gcnVuXG4gICAgIC0gZWFzaW5nIChzdHJpbmcpICNvcHRpb25hbCBlYXNpbmcgdHlwZS4gQWNjZXB0IG9uZSBvZiBAUmFwaGFlbC5lYXNpbmdfZm9ybXVsYXMgb3IgQ1NTIGZvcm1hdDogYGN1YmljJiN4MjAxMDtiZXppZXIoWFgsJiMxNjA7WFgsJiMxNjA7WFgsJiMxNjA7WFgpYFxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uLiBXaWxsIGJlIGNhbGxlZCBhdCB0aGUgZW5kIG9mIGFuaW1hdGlvbi5cbiAgICAgKiBvclxuICAgICAtIGFuaW1hdGlvbiAob2JqZWN0KSBhbmltYXRpb24gb2JqZWN0LCBzZWUgQFJhcGhhZWwuYW5pbWF0aW9uXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLmFuaW1hdGUgPSBmdW5jdGlvbiAocGFyYW1zLCBtcywgZWFzaW5nLCBjYWxsYmFjaykge1xuICAgICAgICB2Y
57590XIgZWxlbWVudCA9IHRoaXM7XG4gICAgICAgIGlmIChlbGVtZW50LnJlbW92ZWQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrLmNhbGwoZWxlbWVudCk7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYW5pbSA9IHBhcmFtcyBpbnN0YW5jZW9mIEFuaW1hdGlvbiA/IHBhcmFtcyA6IFIuYW5pbWF0aW9uKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spO1xuICAgICAgICBydW5BbmltYXRpb24oYW5pbSwgZWxlbWVudCwgYW5pbS5wZXJjZW50c1swXSwgbnVsbCwgZWxlbWVudC5hdHRyKCkpO1xuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnNldFRpbWVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNldHMgdGhlIHN0YXR1cyBvZiBhbmltYXRpb24gb2YgdGhlIGVsZW1lbnQgaW4gbWlsbGlzZWNvbmRzLiBTaW1pbGFyIHRvIEBFbGVtZW50LnN0YXR1cyBtZXRob2QuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGFuaW0gKG9iamVjdCkgYW5pbWF0aW9uIG9iamVjdFxuICAgICAtIHZhbHVlIChudW1iZXIpIG51bWJlciBvZiBtaWxsaXNlY29uZHMgZnJvbSB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhbmltYXRpb25cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KSBvcmlnaW5hbCBlbGVtZW50IGlmIGB2YWx1ZWAgaXMgc3BlY2lmaWVkXG4gICAgICogTm90ZSwgdGhhdCBkdXJpbmcgYW5pbWF0aW9uIGZvbGxvd2luZyBldmVudHMgYXJlIHRyaWdnZXJlZDpcbiAgICAgKlxuICAgICAqIE9uIGVhY2ggYW5pbWF0aW9uIGZyYW1lIGV2ZW50IGBhbmltLmZyYW1lLjxpZD5gLCBvbiBzdGFydCBgYW5pbS5zdGFydC48aWQ+YCBhbmQgb24gZW5kIGBhbmltLmZpbmlzaC48aWQ+YC5cbiAgICBcXCovXG4gICAgZWxwcm90by5zZXRUaW1lID0gZnVuY3Rpb24gKGFuaW0sIHZhbHVlKSB7XG4gICAgICAgIGlmIChhbmltICYmIHZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhdHVzKGFuaW0sIG1taW4odmFsdWUsIGFuaW0ubXMpIC8gYW5pbS5tcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5zdGF0dXNcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEdldHMgb3Igc2V0cyB0aGUgc3RhdHVzIG9mIGFuaW1hdGlvbiBvZiB0aGUgZWxlbWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gYW5pbSAob2JqZWN0KSAjb3B0aW9uYWwgYW5pbWF0aW9uIG9iamVjdFxuICAgICAtIHZhbHVlIChudW1iZXIpICNvcHRpb25hbCAwIOKAkyAxLiBJZiBzcGVjaWZpZWQsIG1ldGhvZCB3b3JrcyBsaWtlIGEgc2V0dGVyIGFuZCBzZXRzIHRoZSBzdGF0dXMgb2YgYSBnaXZlbiBhbmltYXRpb24gdG8gdGhlIHZhbHVlLiBUaGlzIHdpbGwgY2F1c2UgYW5pbWF0aW9uIHRvIGp1bXAgdG8gdGhlIGdpdmVuIHBvc2l0aW9uLlxuICAgICAqKlxuICAgICA9IChudW1iZXIpIHN0YXR1c1xuICAgICAqIG9yXG4gICAgID0gKGFycmF5KSBzdGF0dXMgaWYgYGFuaW1gIGlzIG5vdCBzcGVjaWZpZWQuIEFycmF5IG9mIG9iamVjdHMgaW4gZm9ybWF0OlxuICAgICBvIHtcbiAgICAgbyAgICAgYW5pbTogKG9iamVjdCkgYW5pbWF0aW9uIG9iamVjdFxuICAgICBvICAgICBzdGF0dXM6IChudW1iZXIpIHN0YXR1c1xuICAgICBvIH1cbiAgICAgKiBvclxuICAgICA9IChvYmplY3QpIG9yaWdpbmFsIGVsZW1lbnQgaWYgYHZhbHVlYCBpcyBzcGVjaWZpZWRcbiAgICBcXCovXG4gICAgZWxwcm90by5zdGF0dXMgPSBmdW5jdGlvbiAoYW5pbSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIG91dCA9IFtdLFxuICAgICAgICAgICAgaSA9IDAsXG4gICAgICAgICAgICBsZW4sXG4gICAgICAgICAgICBlO1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcnVuQW5pbWF0aW9uKGFuaW0sIHRoaXMsIC0xLCBtbWluKHZhbHVlLCAxKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxlbiA9IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBlID0gYW5pbWF0aW9uRWxlbWVudHNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGUuZWwuaWQgPT0gdGhpcy5pZCAmJiAoIWFuaW0gfHwgZS5hbmltID09IGFuaW0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhbmltKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZS5zdGF0dXM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3V0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbTogZS5hbmltLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiBlLnN0YXR1c1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYW5pbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQucGF1c2VcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFN0b3BzIGFuaW1hdGlvbiBvZiB0aGUgZWxlbWVudCB3aXRoIGFiaWxpdHkgdG8gcmVzdW1lIGl0IGxhdGVyIG9uLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBhbmltIChvYmplY3QpICNvcHRpb25hbCBhbmltYXRpb24gb2JqZWN0XG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnBhdXNlID0gZnVuY3Rpb24gKGFuaW0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbmltYXRpb25FbGVtZW50cy5sZW5ndGg7IGkrKykgaWYgKGFuaW1hdGlvbkVsZW1lbnRzW2ldLmVsLmlkID09IHRoaXMuaWQgJiYgKCFhbmltIHx8IGFuaW1hdGlvbkVsZW1lbnRzW2ldLmFuaW0gPT0gYW5pbSk
57590pIHtcbiAgICAgICAgICAgIGlmIChldmUoXCJyYXBoYWVsLmFuaW0ucGF1c2UuXCIgKyB0aGlzLmlkLCB0aGlzLCBhbmltYXRpb25FbGVtZW50c1tpXS5hbmltKSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25FbGVtZW50c1tpXS5wYXVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQucmVzdW1lXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXN1bWVzIGFuaW1hdGlvbiBpZiBpdCB3YXMgcGF1c2VkIHdpdGggQEVsZW1lbnQucGF1c2UgbWV0aG9kLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBhbmltIChvYmplY3QpICNvcHRpb25hbCBhbmltYXRpb24gb2JqZWN0XG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnJlc3VtZSA9IGZ1bmN0aW9uIChhbmltKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYW5pbWF0aW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIGlmIChhbmltYXRpb25FbGVtZW50c1tpXS5lbC5pZCA9PSB0aGlzLmlkICYmICghYW5pbSB8fCBhbmltYXRpb25FbGVtZW50c1tpXS5hbmltID09IGFuaW0pKSB7XG4gICAgICAgICAgICB2YXIgZSA9IGFuaW1hdGlvbkVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgaWYgKGV2ZShcInJhcGhhZWwuYW5pbS5yZXN1bWUuXCIgKyB0aGlzLmlkLCB0aGlzLCBlLmFuaW0pICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBlLnBhdXNlZDtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXR1cyhlLmFuaW0sIGUuc3RhdHVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnN0b3BcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFN0b3BzIGFuaW1hdGlvbiBvZiB0aGUgZWxlbWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gYW5pbSAob2JqZWN0KSAjb3B0aW9uYWwgYW5pbWF0aW9uIG9iamVjdFxuICAgICAqKlxuICAgICA9IChvYmplY3QpIG9yaWdpbmFsIGVsZW1lbnRcbiAgICBcXCovXG4gICAgZWxwcm90by5zdG9wID0gZnVuY3Rpb24gKGFuaW0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbmltYXRpb25FbGVtZW50cy5sZW5ndGg7IGkrKykgaWYgKGFuaW1hdGlvbkVsZW1lbnRzW2ldLmVsLmlkID09IHRoaXMuaWQgJiYgKCFhbmltIHx8IGFuaW1hdGlvbkVsZW1lbnRzW2ldLmFuaW0gPT0gYW5pbSkpIHtcbiAgICAgICAgICAgIGlmIChldmUoXCJyYXBoYWVsLmFuaW0uc3RvcC5cIiArIHRoaXMuaWQsIHRoaXMsIGFuaW1hdGlvbkVsZW1lbnRzW2ldLmFuaW0pICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbkVsZW1lbnRzLnNwbGljZShpLS0sIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZnVuY3Rpb24gc3RvcEFuaW1hdGlvbihwYXBlcikge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDsgaSsrKSBpZiAoYW5pbWF0aW9uRWxlbWVudHNbaV0uZWwucGFwZXIgPT0gcGFwZXIpIHtcbiAgICAgICAgICAgIGFuaW1hdGlvbkVsZW1lbnRzLnNwbGljZShpLS0sIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGV2ZS5vbihcInJhcGhhZWwucmVtb3ZlXCIsIHN0b3BBbmltYXRpb24pO1xuICAgIGV2ZS5vbihcInJhcGhhZWwuY2xlYXJcIiwgc3RvcEFuaW1hdGlvbik7XG4gICAgZWxwcm90by50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUmFwaGFcXHhlYmxcXHUyMDE5cyBvYmplY3RcIjtcbiAgICB9O1xuXG4gICAgLy8gU2V0XG4gICAgdmFyIFNldCA9IGZ1bmN0aW9uIChpdGVtcykge1xuICAgICAgICB0aGlzLml0ZW1zID0gW107XG4gICAgICAgIHRoaXMubGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy50eXBlID0gXCJzZXRcIjtcbiAgICAgICAgaWYgKGl0ZW1zKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBpdGVtcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGl0ZW1zW2ldICYmIChpdGVtc1tpXS5jb25zdHJ1Y3RvciA9PSBlbHByb3RvLmNvbnN0cnVjdG9yIHx8IGl0ZW1zW2ldLmNvbnN0cnVjdG9yID09IFNldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1t0aGlzLml0ZW1zLmxlbmd0aF0gPSB0aGlzLml0ZW1zW3RoaXMuaXRlbXMubGVuZ3RoXSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG4gICAgc2V0cHJvdG8gPSBTZXQucHJvdG90eXBlO1xuICAgIC8qXFxcbiAgICAgKiBTZXQucHVzaFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBlYWNoIGFyZ3VtZW50IHRvIHRoZSBjdXJyZW50IHNldC5cbiAgICAgPSAob2JqZWN0KSBvcmlnaW5hbCBlbGVtZW50XG4gICAgXFwqL1xuICAgIHNldHByb3RvLnB1c2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpdGVtLFxuICAgICAgICAgICAgbGVuO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgaXRlbSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGlmIChpdGVtICYmIChpdGVtLmNvbnN0cnVjdG9yID09IGVscHJvdG8uY29uc3RydWN0b3IgfHwgaXRlbS5jb25zdHJ1Y3RvciA9PSBTZXQpKSB7XG4gICAgICAgICAgICAgICAgbGVuID0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdGhpc1tsZW5dID0gdGhpcy5pdGVtc1tsZW5dID0gaXRlbTtcbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgI
57590HJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFNldC5wb3BcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgbGFzdCBlbGVtZW50IGFuZCByZXR1cm5zIGl0LlxuICAgICA9IChvYmplY3QpIGVsZW1lbnRcbiAgICBcXCovXG4gICAgc2V0cHJvdG8ucG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmxlbmd0aCAmJiBkZWxldGUgdGhpc1t0aGlzLmxlbmd0aC0tXTtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXMucG9wKCk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogU2V0LmZvckVhY2hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEV4ZWN1dGVzIGdpdmVuIGZ1bmN0aW9uIGZvciBlYWNoIGVsZW1lbnQgaW4gdGhlIHNldC5cbiAgICAgKlxuICAgICAqIElmIGZ1bmN0aW9uIHJldHVybnMgYGZhbHNlYCBpdCB3aWxsIHN0b3AgbG9vcCBydW5uaW5nLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBjYWxsYmFjayAoZnVuY3Rpb24pIGZ1bmN0aW9uIHRvIHJ1blxuICAgICAtIHRoaXNBcmcgKG9iamVjdCkgY29udGV4dCBvYmplY3QgZm9yIHRoZSBjYWxsYmFja1xuICAgICA9IChvYmplY3QpIFNldCBvYmplY3RcbiAgICBcXCovXG4gICAgc2V0cHJvdG8uZm9yRWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLml0ZW1zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjay5jYWxsKHRoaXNBcmcsIHRoaXMuaXRlbXNbaV0sIGkpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZm9yICh2YXIgbWV0aG9kIGluIGVscHJvdG8pIGlmIChlbHByb3RvW2hhc10obWV0aG9kKSkge1xuICAgICAgICBzZXRwcm90b1ttZXRob2RdID0gKGZ1bmN0aW9uIChtZXRob2RuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxbbWV0aG9kbmFtZV1bYXBwbHldKGVsLCBhcmcpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSkobWV0aG9kKTtcbiAgICB9XG4gICAgc2V0cHJvdG8uYXR0ciA9IGZ1bmN0aW9uIChuYW1lLCB2YWx1ZSkge1xuICAgICAgICBpZiAobmFtZSAmJiBSLmlzKG5hbWUsIGFycmF5KSAmJiBSLmlzKG5hbWVbMF0sIFwib2JqZWN0XCIpKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMCwgamogPSBuYW1lLmxlbmd0aDsgaiA8IGpqOyBqKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1zW2pdLmF0dHIobmFtZVtqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLml0ZW1zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1zW2ldLmF0dHIobmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFNldC5jbGVhclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSB0aGUgc2V0XG4gICAgXFwqL1xuICAgIHNldHByb3RvLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB3aGlsZSAodGhpcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMucG9wKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBTZXQuc3BsaWNlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGdpdmVuIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGluZGV4IChudW1iZXIpIHBvc2l0aW9uIG9mIHRoZSBkZWxldGlvblxuICAgICAtIGNvdW50IChudW1iZXIpIG51bWJlciBvZiBlbGVtZW50IHRvIHJlbW92ZVxuICAgICAtIGluc2VydGlvbuKApiAob2JqZWN0KSAjb3B0aW9uYWwgZWxlbWVudHMgdG8gaW5zZXJ0XG4gICAgID0gKG9iamVjdCkgc2V0IGVsZW1lbnRzIHRoYXQgd2VyZSBkZWxldGVkXG4gICAgXFwqL1xuICAgIHNldHByb3RvLnNwbGljZSA9IGZ1bmN0aW9uIChpbmRleCwgY291bnQsIGluc2VydGlvbikge1xuICAgICAgICBpbmRleCA9IGluZGV4IDwgMCA/IG1tYXgodGhpcy5sZW5ndGggKyBpbmRleCwgMCkgOiBpbmRleDtcbiAgICAgICAgY291bnQgPSBtbWF4KDAsIG1taW4odGhpcy5sZW5ndGggLSBpbmRleCwgY291bnQpKTtcbiAgICAgICAgdmFyIHRhaWwgPSBbXSxcbiAgICAgICAgICAgIHRvZGVsID0gW10sXG4gICAgICAgICAgICBhcmdzID0gW10sXG4gICAgICAgICAgICBpO1xuICAgICAgICBmb3IgKGkgPSAyOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzLnB1c2goYXJndW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgdG9kZWwucHVzaCh0aGlzW2luZGV4ICsgaV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoOyBpIDwgdGhpcy5sZW5ndGggLSBpbmRleDsgaSsrKSB7XG4gICAgICAgICAgICB0YWlsLnB1c2godGhpc1tpbmRleCArIGldKTtcbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgYXJnbGVuID0gYXJncy5sZW5ndGg7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBhcmdsZW4gKyB0YWlsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLml0ZW1zW2luZGV4ICsgaV0gPSB0aGlzW2luZGV4ICsgaV0gPSBpIDwgYXJnbGVuID8gYXJnc1tpXSA6IHRhaWxbaSAtIGFyZ2xlbl07XG4gICAgICAgIH1cbiAgICAgICAgaSA9IHRoaXMuaXRlbXMubGVuZ3RoID0gdGhpcy5sZW5ndGggLT0gY291bnQgLSBhcmdsZW47XG4gICAgICAgIHdoaWxlICh0aGlzW2ldKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpc1tpKytdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2V0KHRvZGVsKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBTZXQuZXhjbHVkZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBnaXZlbiBlbGVtZW50IGZyb20gdGhlIHNldFxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBlbGVtZW50IChvYmplY3QpIGVsZW1lbnQgdG8gcmVtb3ZlXG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCBpZiBvYmplY3Qgd2FzIGZvdW5kICYgcmVtb3ZlZCBmcm9tIHRoZSBzZXRcbiAgICBcXCovXG4gICAgc2V0cHJvdG8uZXhjbHVkZSA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLmxlbmd0aDsgaSA8IGlpOyBpKyspIGlmICh0aGlzW2ldID09IGVsKSB7XG4gICAgICAgICAgICB0aGlzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBzZXRwcm90by5hbmltYXRlID0gZnVuY3Rpb24gKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spIHtcbiAgICAgICAgKFIuaXMoZWFzaW5nLCBcImZ1bmN0aW9uXCIpIHx8ICFlYXNpbmcpICYmIChjYWxsYmFjayA9IGVhc2luZyB8fCBudWxsKTtcbiAgICAgICAgdmFyIGxlbiA9IHRoaXMuaXRlbXMubGVuZ3RoLFxuICAgICAgICAgICAgaSA9IGxlbixcbiAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICBzZXQgP
57590SB0aGlzLFxuICAgICAgICAgICAgY29sbGVjdG9yO1xuICAgICAgICBpZiAoIWxlbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgY2FsbGJhY2sgJiYgKGNvbGxlY3RvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICEtLWxlbiAmJiBjYWxsYmFjay5jYWxsKHNldCk7XG4gICAgICAgIH0pO1xuICAgICAgICBlYXNpbmcgPSBSLmlzKGVhc2luZywgc3RyaW5nKSA/IGVhc2luZyA6IGNvbGxlY3RvcjtcbiAgICAgICAgdmFyIGFuaW0gPSBSLmFuaW1hdGlvbihwYXJhbXMsIG1zLCBlYXNpbmcsIGNvbGxlY3Rvcik7XG4gICAgICAgIGl0ZW0gPSB0aGlzLml0ZW1zWy0taV0uYW5pbWF0ZShhbmltKTtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgdGhpcy5pdGVtc1tpXSAmJiAhdGhpcy5pdGVtc1tpXS5yZW1vdmVkICYmIHRoaXMuaXRlbXNbaV0uYW5pbWF0ZVdpdGgoaXRlbSwgYW5pbSwgYW5pbSk7XG4gICAgICAgICAgICAodGhpcy5pdGVtc1tpXSAmJiAhdGhpcy5pdGVtc1tpXS5yZW1vdmVkKSB8fCBsZW4tLTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIHNldHByb3RvLmluc2VydEFmdGVyID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBpID0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIHRoaXMuaXRlbXNbaV0uaW5zZXJ0QWZ0ZXIoZWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgc2V0cHJvdG8uZ2V0QkJveCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHggPSBbXSxcbiAgICAgICAgICAgIHkgPSBbXSxcbiAgICAgICAgICAgIHgyID0gW10sXG4gICAgICAgICAgICB5MiA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5pdGVtcy5sZW5ndGg7IGktLTspIGlmICghdGhpcy5pdGVtc1tpXS5yZW1vdmVkKSB7XG4gICAgICAgICAgICB2Y
57590XIgYm94ID0gdGhpcy5pdGVtc1tpXS5nZXRCQm94KCk7XG4gICAgICAgICAgICB4LnB1c2goYm94LngpO1xuICAgICAgICAgICAgeS5wdXNoKGJveC55KTtcbiAgICAgICAgICAgIHgyLnB1c2goYm94LnggKyBib3gud2lkdGgpO1xuICAgICAgICAgICAgeTIucHVzaChib3gueSArIGJveC5oZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIHggPSBtbWluW2FwcGx5XSgwLCB4KTtcbiAgICAgICAgeSA9IG1taW5bYXBwbHldKDAsIHkpO1xuICAgICAgICB4MiA9IG1tYXhbYXBwbHldKDAsIHgyKTtcbiAgICAgICAgeTIgPSBtbWF4W2FwcGx5XSgwLCB5Mik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgeTogeSxcbiAgICAgICAgICAgIHgyOiB4MixcbiAgICAgICAgICAgIHkyOiB5MixcbiAgICAgICAgICAgIHdpZHRoOiB4MiAtIHgsXG4gICAgICAgICAgICBoZWlnaHQ6IHkyIC0geVxuICAgICAgICB9O1xuICAgIH07XG4gICAgc2V0cHJvdG8uY2xvbmUgPSBmdW5jdGlvbiAocykge1xuICAgICAgICBzID0gdGhpcy5wYXBlci5zZXQoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGhpcy5pdGVtcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBzLnB1c2godGhpcy5pdGVtc1tpXS5jbG9uZSgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcztcbiAgICB9O1xuICAgIHNldHByb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSYXBoYVxceGVibFxcdTIwMThzIHNldFwiO1xuICAgIH07XG5cbiAgICBzZXRwcm90by5nbG93ID0gZnVuY3Rpb24oZ2xvd0NvbmZpZykge1xuICAgICAgICB2Y
57590XIgcmV0ID0gdGhpcy5wYXBlci5zZXQoKTtcbiAgICAgICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHNoYXBlLCBpbmRleCl7XG4gICAgICAgICAgICB2YXIgZyA9IHNoYXBlLmdsb3coZ2xvd0NvbmZpZyk7XG4gICAgICAgICAgICBpZihnICE9IG51bGwpe1xuICAgICAgICAgICAgICAgIGcuZm9yRWFjaChmdW5jdGlvbihzaGFwZTIsIGluZGV4Mil7XG4gICAgICAgICAgICAgICAgICAgIHJldC5wdXNoKHNoYXBlMik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH07XG5cblxuICAgIC8qXFxcbiAgICAgKiBTZXQuaXNQb2ludEluc2lkZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogRGV0ZXJtaW5lIGlmIGdpdmVuIHBvaW50IGlzIGluc2lkZSB0aGlzIHNldOKAmXMgZWxlbWVudHNcbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgIC0geSAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCBpZiBwb2ludCBpcyBpbnNpZGUgYW55IG9mIHRoZSBzZXQncyBlbGVtZW50c1xuICAgICBcXCovXG4gICAgc2V0cHJvdG8uaXNQb2ludEluc2lkZSA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIHZhciBpc1BvaW50SW5zaWRlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbC5pc1BvaW50SW5zaWRlKHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgaXNQb2ludEluc2lkZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBzdG9wIGxvb3BcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBpc1BvaW50SW5zaWRlO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5yZWdpc3RlckZvbnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZ2l2ZW4gZm9udCB0byB0aGUgcmVnaXN0ZXJlZCBzZXQgb2YgZm9udHMgZm9yIFJhcGhhw6tsLiBTaG91bGQgYmUgdXNlZCBhcyBhbiBpbnRlcm5hbCBjYWxsIGZyb20gd2l0aGluIEN1ZsOzbuKAmXMgZm9udCBmaWxlLlxuICAgICAqIFJldHVybnMgb3JpZ2luYWwgcGFyYW1ldGVyLCBzbyBpdCBjb3VsZCBiZSB1c2VkIHdpdGggY2hhaW5pbmcuXG4gICAgICMgPGEgaHJlZj1cImh0dHA6Ly93aWtpLmdpdGh1Yi5jb20vc29yY2N1L2N1Zm9uL2Fib3V0XCI+TW9yZSBhYm91dCBDdWbDs24gYW5kIGhvdyB0byBjb252ZXJ0IHlvdXIgZm9udCBmb3JtIFRURiwgT1RGLCBldGMgdG8gSmF2YVNjcmlwdCBmaWxlLjwvYT5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gZm9udCAob2JqZWN0KSB0aGUgZm9udCB0byByZWdpc3RlclxuICAgICA9IChvYmplY3QpIHRoZSBmb250IHlvdSBwYXNzZWQgaW5cbiAgICAgPiBVc2FnZVxuICAgICB8IEN1Zm9uLnJlZ2lzdGVyRm9udChSYXBoYWVsLnJlZ2lzdGVyRm9udCh74oCmfSkpO1xuICAgIFxcKi9cbiAgICBSLnJlZ2lzdGVyRm9udCA9IGZ1bmN0aW9uIChmb250KSB7XG4gICAgICAgIGlmICghZm9udC5mYWNlKSB7XG4gICAgICAgICAgICByZXR1cm4gZm9udDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvbnRzID0gdGhpcy5mb250cyB8fCB7fTtcbiAgICAgICAgdmFyIGZvbnRjb3B5ID0ge1xuICAgICAgICAgICAgICAgIHc6IGZvbnQudyxcbiAgICAgICAgICAgICAgICBmYWNlOiB7fSxcbiAgICAgICAgICAgICAgICBnbHlwaHM6IHt9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmFtaWx5ID0gZm9udC5mYWNlW1wiZm9udC1mYW1pbHlcIl07XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gZm9udC5mYWNlKSBpZiAoZm9udC5mYWNlW2hhc10ocHJvcCkpIHtcbiAgICAgICAgICAgIGZvbnRjb3B5LmZhY2VbcHJvcF0gPSBmb250LmZhY2VbcHJvcF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZm9udHNbZmFtaWx5XSkge1xuICAgICAgICAgICAgdGhpcy5mb250c1tmYW1pbHldLnB1c2goZm9udGNvcHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5mb250c1tmYW1pbHldID0gW2ZvbnRjb3B5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZvbnQuc3ZnKSB7XG4gICAgICAgICAgICBmb250Y29weS5mYWNlW1widW5pdHMtcGVyLWVtXCJdID0gdG9JbnQoZm9udC5mYWNlW1widW5pdHMtcGVyLWVtXCJdLCAxMCk7XG4gICAgICAgICAgICBmb3IgKHZhciBnbHlwaCBpbiBmb250LmdseXBocykgaWYgKGZvbnQuZ2x5cGhzW2hhc10oZ2x5cGgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGggPSBmb250LmdseXBoc1tnbHlwaF07XG4gICAgICAgICAgICAgICAgZm9udGNvcHkuZ2x5cGhzW2dseXBoXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgdzogcGF0aC53LFxuICAgICAgICAgICAgICAgICAgICBrOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgZDogcGF0aC5kICYmIFwiTVwiICsgcGF0aC5kLnJlcGxhY2UoL1ttbGN4dHJ2XS9nLCBmdW5jdGlvbiAoY29tbWFuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7bDogXCJMXCIsIGM6IFwiQ1wiLCB4OiBcInpcIiwgdDogXCJtXCIsIHI6IFwibFwiLCB2OiBcImNcIn1bY29tbWFuZF0gfHwgXCJNXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSArIFwielwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAocGF0aC5rKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcGF0aC5rKSBpZiAocGF0aFtoYXNdKGspKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb250Y29weS5nbHlwaHNbZ2x5cGhdLmtba10gPSBwYXRoLmtba107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZvbnQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIuZ2V0Rm9udFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogRmluZHMgZm9udCBvYmplY3QgaW4gdGhlIHJlZ2lzdGVyZWQgZm9udHMgYnkgZ2l2ZW4gcGFyYW1ldGVycy4gWW91IGNvdWxkIHNwZWNpZnkgb25seSBvbmUgd29yZCBmcm9tIHRoZSBmb250IG5hbW
57590UsIGxpa2Ug4oCcTXlyaWFk4oCdIGZvciDigJxNeXJpYWQgUHJv4oCdLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBmYW1pbHkgKHN0cmluZykgZm9udCBmYW1pbHkgbmFtZSBvciBhbnkgd29yZCBmcm9tIGl0XG4gICAgIC0gd2VpZ2h0IChzdHJpbmcpICNvcHRpb25hbCBmb250IHdlaWdodFxuICAgICAtIHN0eWxlIChzdHJpbmcpICNvcHRpb25hbCBmb250IHN0eWxlXG4gICAgIC0gc3RyZXRjaCAoc3RyaW5nKSAjb3B0aW9uYWwgZm9udCBzdHJldGNoXG4gICAgID0gKG9iamVjdCkgdGhlIGZvbnQgb2JqZWN0XG4gICAgID4gVXNhZ2VcbiAgICAgfCBwYXBlci5wcmludCgxMDAsIDEwMCwgXCJUZXN0IHN0cmluZ1wiLCBwYXBlci5nZXRGb250KFwiVGltZXNcIiwgODAwKSwgMzApO1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmdldEZvbnQgPSBmdW5jdGlvbiAoZmFtaWx5LCB3ZWlnaHQsIHN0eWxlLCBzdHJldGNoKSB7XG4gICAgICAgIHN0cmV0Y2ggPSBzdHJldGNoIHx8IFwibm9ybWFsXCI7XG4gICAgICAgIHN0eWxlID0gc3R5bGUgfHwgXCJub3JtYWxcIjtcbiAgICAgICAgd2VpZ2h0ID0gK3dlaWdodCB8fCB7bm9ybWFsOiA0MDAsIGJvbGQ6IDcwMCwgbGlnaHRlcjogMzAwLCBib2xkZXI6IDgwMH1bd2VpZ2h0XSB8fCA0MDA7XG4gICAgICAgIGlmICghUi5mb250cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmb250ID0gUi5mb250c1tmYW1pbHldO1xuICAgICAgICBpZiAoIWZvbnQpIHtcbiAgICAgICAgICAgIHZhciBuYW1lID0gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgZmFtaWx5LnJlcGxhY2UoL1teXFx3XFxkXFxzKyF+LjpfLV0vZywgRSkgKyBcIihcXFxcc3wkKVwiLCBcImlcIik7XG4gICAgICAgICAgICBmb3IgKHZhciBmb250TmFtZSBpbiBSLmZvbnRzKSBpZiAoUi5mb250c1toYXNdKGZvbnROYW1lKSkge1xuICAgICAgICAgICAgICAgIGlmIChuYW1lLnRlc3QoZm9udE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvbnQgPSBSLmZvbnRzW2ZvbnROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciB0aGVmb250O1xuICAgICAgICBpZiAoZm9udCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZm9udC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhlZm9udCA9IGZvbnRbaV07XG4gICAgICAgICAgICAgICAgaWYgKHRoZWZvbnQuZmFjZVtcImZvbnQtd2VpZ2h0XCJdID09IHdlaWdodCAmJiAodGhlZm9udC5mYWNlW1wiZm9udC1zdHlsZVwiXSA9PSBzdHlsZSB8fCAhdGhlZm9udC5mYWNlW1wiZm9udC1zdHlsZVwiXSkgJiYgdGhlZm9udC5mYWNlW1wiZm9udC1zdHJldGNoXCJdID09IHN0cmV0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGVmb250O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnByaW50XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIHBhdGggdGhhdCByZXByZXNlbnQgZ2l2ZW4gdGV4dCB3cml0dGVuIHVzaW5nIGdpdmVuIGZvbnQgYXQgZ2l2ZW4gcG9zaXRpb24gd2l0aCBnaXZlbiBzaXplLlxuICAgICAqIFJlc3VsdCBvZiB0aGUgbWV0aG9kIGlzIHBhdGggZWxlbWVudCB0aGF0IGNvbnRhaW5zIHdob2xlIHRleHQgYXMgYSBzZXBhcmF0ZSBwYXRoLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggcG9zaXRpb24gb2YgdGhlIHRleHRcbiAgICAgLSB5IChudW1iZXIpIHkgcG9zaXRpb24gb2YgdGhlIHRleHRcbiAgICAgLSBzdHJpbmcgKHN0cmluZykgdGV4dCB0byBwcmludFxuICAgICAtIGZvbnQgKG9iamVjdCkgZm9udCBvYmplY3QsIHNlZSBAUGFwZXIuZ2V0Rm9udFxuICAgICAtIHNpemUgKG51bWJlcikgI29wdGlvbmFsIHNpemUgb2YgdGhlIGZvbnQsIGRlZmF1bHQgaXMgYDE2YFxuICAgICAtIG9yaWdpbiAoc3RyaW5nKSAjb3B0aW9uYWwgY291bGQgYmUgYFwiYmFzZWxpbmVcImAgb3IgYFwibWlkZGxlXCJgLCBkZWZhdWx0IGlzIGBcIm1pZGRsZVwiYFxuICAgICAtIGxldHRlcl9zcGFjaW5nIChudW1iZXIpICNvcHRpb25hbCBudW1iZXIgaW4gcmFuZ2UgYC0xLi4xYCwgZGVmYXVsdCBpcyBgMGBcbiAgICAgLSBsaW5lX3NwYWNpbmcgKG51bWJlcikgI29wdGlvbmFsIG51bWJlciBpbiByYW5nZSBgMS4uM2AsIGRlZmF1bHQgaXMgYDFgXG4gICAgID0gKG9iamVjdCkgcmVzdWx0aW5nIHBhdGggZWxlbWVudCwgd2hpY2ggY29uc2lzdCBvZiBhbGwgbGV0dGVyc1xuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIHR4dCA9IHIucHJpbnQoMTAsIDUwLCBcInByaW50XCIsIHIuZ2V0Rm9udChcIk11c2VvXCIpLCAzMCkuYXR0cih7ZmlsbDogXCIjZmZmXCJ9KTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5wcmludCA9IGZ1bmN0aW9uICh4LCB5LCBzdHJpbmcsIGZvbnQsIHNpemUsIG9yaWdpbiwgbGV0dGVyX3NwYWNpbmcsIGxpbmVfc3BhY2luZykge1xuICAgICAgICBvcmlnaW4gPSBvcmlnaW4gfHwgXCJtaWRkbGVcIjsgLy8gYmFzZWxpbmV8bWlkZGxlXG4gICAgICAgIGxldHRlcl9zcGFjaW5nID0gbW1heChtbWluKGxldHRlcl9zcGFjaW5nIHx8IDAsIDEpLCAtMSk7XG4gICAgICAgIGxpbmVfc3BhY2luZyA9IG1tYXgobW1pbihsaW5lX3NwYWNpbmcgfHwgMSwgMyksIDEpO1xuICAgICAgICB2Y
57590XIgbGV0dGVycyA9IFN0cihzdHJpbmcpW3NwbGl0XShFKSxcbiAgICAgICAgICAgIHNoaWZ0ID0gMCxcbiAgICAgICAgICAgIG5vdGZpcnN0ID0gMCxcbiAgICAgICAgICAgIHBhdGggPSBFLFxuICAgICAgICAgICAgc2NhbGU7XG4gICAgICAgIFIuaXMoZm9udCwgXCJzdHJpbmdcIikgJiYgKGZvbnQgPSB0aGlzLmdldEZvbnQoZm9udCkpO1xuICAgICAgICBpZiAoZm9udCkge1xuICAgICAgICAgICAgc2NhbGUgPSAoc2l6ZSB8fCAxNikgLyBmb250LmZhY2VbXCJ1bml0cy1wZXItZW1cIl07XG4gICAgICAgICAgICB2YXIgYmIgPSBmb250LmZhY2UuYmJveFtzcGxpdF0oc2VwYXJhdG9yKSxcbiAgICAgICAgICAgICAgICB0b3AgPSArYmJbMF0sXG4gICAgICAgICAgICAgICAgbGluZUhlaWdodCA9IGJiWzNdIC0gYmJbMV0sXG4gICAgICAgICAgICAgICAgc2hpZnR5ID0gMCxcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSArYmJbMV0gKyAob3JpZ2luID09IFwiYmFzZWxpbmVcIiA/IGxpbmVIZWlnaHQgKyAoK2ZvbnQuZmFjZS5kZXNjZW50KSA6IGxpbmVIZWlnaHQgLyAyKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGxldHRlcnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChsZXR0ZXJzW2ldID09IFwiXFxuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyID0gMDtcbiAgICAgICAgICAgICAgICAgICAgbm90Zmlyc3QgPSAwO1xuICAgICAgICAgICAgICAgICAgICBzaGlmdHkgKz0gbGluZUhlaWdodCAqIGxpbmVfc3BhY2luZztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgcHJldiA9IG5vdGZpcnN0ICYmIGZvbnQuZ2x5cGhzW2xldHRlcnNbaSAtIDFdXSB8fCB7fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnIgPSBmb250LmdseXBoc1tsZXR0ZXJzW2ldXTtcbiAgICAgICAgICAgICAgICAgICAgc2hpZnQgKz0gbm90Zmlyc3QgPyAocHJldi53IHx8IGZvbnQudykgKyAocHJldi5rICYmIHByZXYua1tsZXR0ZXJzW2ldXSB8fCAwKSArIChmb250LncgKiBsZXR0ZXJfc3BhY2luZykgOiAwO1xuICAgICAgICAgICAgICAgICAgICBub3RmaXJzdCA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyICYmIGN1cnIuZCkge1xuICAgICAgICAgICAgICAgICAgICBwYXRoICs9IFIudHJhbnNmb3JtUGF0aChjdXJyLmQsIFtcInRcIiwgc2hpZnQgKiBzY2FsZSwgc2hpZnR5ICogc2NhbGUsIFwic1wiLCBzY2FsZSwgc2NhbGUsIHRvcCwgaGVpZ2h0LCBcInRcIiwgKHggLSB0b3ApIC8gc2NhbGUsICh5IC0gaGVpZ2h0KSAvIHNjYWxlXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnBhdGgocGF0aCkuYXR0cih7XG4gICAgICAgICAgICBmaWxsOiBcIiMwMDBcIixcbiAgICAgICAgICAgIHN0cm9rZTogXCJub25lXCJcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qXFxcbiAgICAgKiBQYXBlci5hZGRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEltcG9ydHMgZWxlbWVudHMgaW4gSlNPTiBhcnJheSBpbiBmb3JtYXQgYHt0eXBlOiB0eXBlLCA8YXR0cmlidXRlcz59YFxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBqc29uIChhcnJheSlcbiAgICAgPSAob2JqZWN0KSByZXN1bHRpbmcgc2V0IG9mIGltcG9ydGVkIGVsZW1lbnRzXG4gICAgID4gVXNhZ2VcbiAgICAgfCBwYXBlci5hZGQoW1xuICAgICB8ICAgICB7XG4gICAgIHwgICAgICAgICB0eXBlOiBcImNpcmNsZVwiLFxuICAgICB8ICAgICAgICAgY3g6IDEwLFxuICAgICB8ICAgICAgICAgY3k6IDEwLFxuICAgICB8ICAgICAgICAgcjogNVxuICAgICB8ICAgICB9LFxuICAgICB8ICAgICB7XG4gICAgIHwgICAgICAgICB0eXBlOiBcInJlY3RcIixcbiAgICAgfCAgICAgICAgIHg6IDEwLFxuICAgICB8ICAgICAgICAgeTogMTAsXG4gICAgIHwgICAgICAgICB3aWR0aDogMTAsXG4gICAgIHwgICAgICAgICBoZWlnaHQ6IDEwLFxuICAgICB8ICAgICAgICAgZmlsbDogXCIjZmMwXCJcbiAgICAgfCAgICAgfVxuICAgICB8IF0pO1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmFkZCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIGlmIChSLmlzKGpzb24sIFwiYXJyYXlcIikpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSB0aGlzLnNldCgpLFxuICAgICAgICAgICAgICAgIGkgPSAwLFxuICAgICAgICAgICAgICAgIGlpID0ganNvbi5sZW5ndGgsXG4gICAgICAgICAgICAgICAgajtcbiAgICAgICAgICAgIGZvciAoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGogPSBqc29uW2ldIHx8IHt9O1xuICAgICAgICAgICAgICAgIGVsZW1lbnRzW2hhc10oai50eXBlKSAmJiByZXMucHVzaCh0aGlzW2oudHlwZV0oKS5hdHRyKGopKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5mb3JtYXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNpbXBsZSBmb3JtYXQgZnVuY3Rpb24uIFJlcGxhY2VzIGNvbnN0cnVjdGlvbiBvZiB0eXBlIOKAnGB7PG51bWJlcj59YOKAnSB0byB0aGUgY29ycmVzcG9uZGluZyBhcmd1bWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gdG9rZW4gKHN0cmluZykgc3RyaW5nIHRvIGZvcm1hdFxuICAgICAtIOKApiAoc3RyaW5nKSByZXN0IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHRyZWF0ZWQgYXMgcGFyYW1ldGVycyBmb3IgcmVwbGFjZW1lbnRcbiAgICAgPSAoc3RyaW5nKSBmb3JtYXRlZCBzdHJpbmdcbiAgICAgPiBVc2FnZVxuICAgICB8IHZhciB4ID0gMTAsXG4gICAgIHwgICAgIHkgPSAyMCxcbiAgICAgfCAgICAgd2lkdGggPSA0MCxcbiAgICAgfCAgICAgaGVpZ2h0ID0gNTA7XG4gICAgIHwgLy8gdGhpcyB3aWxsIGRyYXcgYSByZWN0YW5ndWxhciBzaGFwZSBlcXVpdmFsZW50IHRvIFwiTTEwLDIwaDQwdjUwaC00MHpcIlxuICAgICB8IHBhcGVyLnBhdGgoUmFwaGFlbC5mb3JtYXQoXCJNezB9LHsxfWh7Mn12ezN9aHs0fXpcIiwgeCwgeSwgd2lkdGgsIGhlaWdodCwgLXdpZHRoKSk7XG4gICAgXFwqL1xuICAgIFIuZm9ybWF0ID0gZnVuY3Rpb24gKHRva2VuLCBwYXJhbXMpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBSLmlzKHBhcmFtcywgYXJyYXkpID8gWzBdW2NvbmNhdF0ocGFyYW1zKSA6IGFyZ3VtZW50cztcbiAgICAgICAgdG9rZW4gJiYgUi5pcyh0b2tlbiwgc3RyaW5nKSAmJiBhcmdzLmxlbmd0aCAtIDEgJiYgKHRva2VuID0gdG9rZW4ucmVwbGFjZShmb3JtYXRyZywgZnVuY3Rpb24gKHN0ciwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3NbKytpXSA9PSBudWxsID8gRSA6IGFyZ3NbaV07XG4gICAgICAgIH0pKTtcbiAgICAgICAgcmV0dXJuIHRva2VuIHx8IEU7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5mdWxsZmlsbFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQSBsaXR0bGUgYml0IG1vcmUgYWR2YW5jZWQgZm9ybWF0IGZ1bmN0aW9uIHRoYW4gQFJhcGhhZWwuZm9ybWF0LiBSZXBsYWNlcyBjb25zdHJ1Y3Rpb24gb2YgdHlwZSDigJxgezxuYW1lPn1g4oCdIHRvIHRoZSBjb3JyZXNwb25kaW5nIGFyZ3VtZW50LlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB0b2tlbiAoc3RyaW5nKSBzdHJpbmcgdG8gZm9ybWF0XG4gICAgIC0ganNvbiAob2JqZWN0KSBvYmplY3Qgd2hpY2ggcHJvcGVydGllcyB3aWxsIGJlIHVzZWQgYXMgYSByZXBsYWNlbWVudFxuICAgICA9IChzdHJpbmcpIGZvcm1hdGVkIHN0cmluZ1xuICAgICA+IFVzYWdlXG4gICAgI
57590HwgLy8gdGhpcyB3aWxsIGRyYXcgYSByZWN0YW5ndWxhciBzaGFwZSBlcXVpdmFsZW50IHRvIFwiTTEwLDIwaDQwdjUwaC00MHpcIlxuICAgICB8IHBhcGVyLnBhdGgoUmFwaGFlbC5mdWxsZmlsbChcIk17eH0se3l9aHtkaW0ud2lkdGh9dntkaW0uaGVpZ2h0fWh7ZGltWyduZWdhdGl2ZSB3aWR0aCddfXpcIiwge1xuICAgICB8ICAgICB4OiAxMCxcbiAgICAgfCAgICAgeTogMjAsXG4gICAgIHwgICAgIGRpbToge1xuICAgICB8ICAgICAgICAgd2lkdGg6IDQwLFxuICAgICB8ICAgICAgICAgaGVpZ2h0OiA1MCxcbiAgICAgfCAgICAgICAgIFwibmVnYXRpdmUgd2lkdGhcIjogLTQwXG4gICAgIHwgICAgIH1cbiAgICAgfCB9KSk7XG4gICAgXFwqL1xuICAgIFIuZnVsbGZpbGwgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdG9rZW5SZWdleCA9IC9cXHsoW15cXH1dKylcXH0vZyxcbiAgICAgICAgICAgIG9iak5vdGF0aW9uUmVnZXggPSAvKD86KD86XnxcXC4pKC4rPykoPz1cXFt8XFwufCR8XFwoKXxcXFsoJ3xcIikoLis/KVxcMlxcXSkoXFwoXFwpKT8vZywgLy8gbWF0Y2hlcyAueHh4eHggb3IgW1wieHh4eHhcIl0gdG8gcnVuIG92ZXIgb2JqZWN0IHByb3BlcnRpZXNcbiAgICAgICAgICAgIHJlcGxhY2VyID0gZnVuY3Rpb24gKGFsbCwga2V5LCBvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gb2JqO1xuICAgICAgICAgICAgICAgIGtleS5yZXBsYWNlKG9iak5vdGF0aW9uUmVnZXgsIGZ1bmN0aW9uIChhbGwsIG5hbWUsIHF1b3RlLCBxdW90ZWROYW1lLCBpc0Z1bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZSA9IG5hbWUgfHwgcXVvdGVkTmFtZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgaW4gcmVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gcmVzW25hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHJlcyA9PSBcImZ1bmN0aW9uXCIgJiYgaXNGdW5jICYmIChyZXMgPSByZXMoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXMgPSAocmVzID09IG51bGwgfHwgcmVzID09IG9iaiA/IGFsbCA6IHJlcykgKyBcIlwiO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9O1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHN0ciwgb2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKHN0cikucmVwbGFjZSh0b2tlblJlZ2V4LCBmdW5jdGlvbiAoYWxsLCBrZXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZXIoYWxsLCBrZXksIG9iaik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9KSgpO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLm5pbmphXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBsZWF2ZSBubyB0cmFjZSBvZiBSYXBoYcOrbCAoV2VsbCwgUmFwaGHDq2wgY3JlYXRlcyBvbmx5IG9uZSBnbG9iYWwgdmFyaWFibGUgYFJhcGhhZWxgLCBidXQgYW55d2F5LikgWW91IGNhbiB1c2UgYG5pbmphYCBtZXRob2QuXG4gICAgICogQmV3YXJlLCB0aGF0IGluIHRoaXMgY2FzZSBwbHVnaW5zIGNvdWxkIHN0b3Agd29ya2luZywgYmVjYXVzZSB0aGV5IGFyZSBkZXBlbmRpbmcgb24gZ2xvYmFsIHZhcmlhYmxlIGV4aXN0ZW5jZS5cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KSBSYXBoYWVsIG9iamVjdFxuICAgICA+IFVzYWdlXG4gICAgIHwgKGZ1bmN0aW9uIChsb2NhbF9yYXBoYWVsKSB7XG4gICAgIHwgICAgIHZhciBwYXBlciA9IGxvY2FsX3JhcGhhZWwoMTAsIDEwLCAzMjAsIDIwMCk7XG4gICAgI
57590HwgICAgIOKAplxuICAgICB8IH0pKFJhcGhhZWwubmluamEoKSk7XG4gICAgXFwqL1xuICAgIFIubmluamEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChvbGRSYXBoYWVsLndhcykge1xuICAgICAgICAgICAgZy53aW4uUmFwaGFlbCA9IG9sZFJhcGhhZWwuaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJRTggcmFpc2VzIGFuIGVycm9yIHdoZW4gZGVsZXRpbmcgd2luZG93IHByb3BlcnR5XG4gICAgICAgICAgICB3aW5kb3cuUmFwaGFlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHdpbmRvdy5SYXBoYWVsO1xuICAgICAgICAgICAgfSBjYXRjaChlKSB7fVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuc3RcbiAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICoqXG4gICAgICogWW91IGNhbiBhZGQgeW91ciBvd24gbWV0aG9kIHRvIGVsZW1lbnRzIGFuZCBzZXRzLiBJdCBpcyB3aXNlIHRvIGFkZCBhIHNldCBtZXRob2QgZm9yIGVhY2ggZWxlbWVudCBtZXRob2RcbiAgICAgKiB5b3UgYWRkZWQsIHNvIHlvdSB3aWxsIGJlIGFibGUgdG8gY2FsbCB0aGUgc2FtZSBtZXRob2Qgb24gc2V0cyB0b28uXG4gICAgICoqXG4gICAgICogU2VlIGFsc28gQFJhcGhhZWwuZWwuXG4gICAgID4gVXNhZ2VcbiAgICAgfCBSYXBoYWVsLmVsLnJlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgfCAgICAgdGhpcy5hdHRyKHtmaWxsOiBcIiNmMDBcIn0pO1xuICAgICB8IH07XG4gICAgIHwgUmFwaGFlbC5zdC5yZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgIHwgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgfCAgICAgICAgIGVsLnJlZCgpO1xuICAgICB8ICAgICB9KTtcbiAgICAgfCB9O1xuICAgICB8IC8vIHRoZW4gdXNlIGl0XG4gICAgI
57590HwgcGFwZXIuc2V0KHBhcGVyLmNpcmNsZSgxMDAsIDEwMCwgMjApLCBwYXBlci5jaXJjbGUoMTEwLCAxMDAsIDIwKSkucmVkKCk7XG4gICAgXFwqL1xuICAgIFIuc3QgPSBzZXRwcm90bztcblxuICAgIGV2ZS5vbihcInJhcGhhZWwuRE9NbG9hZFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxvYWRlZCA9IHRydWU7XG4gICAgfSk7XG5cbiAgICAvLyBGaXJlZm94IDwzLjYgZml4OiBodHRwOi8vd2VicmVmbGVjdGlvbi5ibG9nc3BvdC5jb20vMjAwOS8xMS8xOTUtY2hhcnMtdG8taGVscC1sYXp5LWxvYWRpbmcuaHRtbFxuICAgIChmdW5jdGlvbiAoZG9jLCBsb2FkZWQsIGYpIHtcbiAgICAgICAgaWYgKGRvYy5yZWFkeVN0YXRlID09IG51bGwgJiYgZG9jLmFkZEV2ZW50TGlzdGVuZXIpe1xuICAgICAgICAgICAgZG9jLmFkZEV2ZW50TGlzdGVuZXIobG9hZGVkLCBmID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKGxvYWRlZCwgZiwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGRvYy5yZWFkeVN0YXRlID0gXCJjb21wbGV0ZVwiO1xuICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgZG9jLnJlYWR5U3RhdGUgPSBcImxvYWRpbmdcIjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0xvYWRlZCgpIHtcbiAgICAgICAgICAgICgvaW4vKS50ZXN0KGRvYy5yZWFkeVN0YXRlKSA/IHNldFRpbWVvdXQoaXNMb2FkZWQsIDkpIDogUi5ldmUoXCJyYXBoYWVsLkRPTWxvYWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaXNMb2FkZWQoKTtcbiAgICB9KShkb2N1bWVudCwgXCJET01Db250ZW50TG9hZGVkXCIpO1xuXG4gICAgcmV0dXJuIFI7XG59KTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ
57590UNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO
575900FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./dev/raphael.core.js\n");
57591
57592/***/ }),
57593
57594/***/ "./dev/raphael.svg.js":
57595/*!****************************!*\
57596  !*** ./dev/raphael.svg.js ***!
57597  \****************************/
57598/*! no static exports found */
57599/***/ (function(module, exports, __webpack_require__) {
57600
57601eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ \"./dev/raphael.core.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {\n    if (R && !R.svg) {\n        return;\n    }\n\n    var has = \"hasOwnProperty\",\n        Str = String,\n        toFloat = parseFloat,\n        toInt = parseInt,\n        math = Math,\n        mmax = math.max,\n        abs = math.abs,\n        pow = math.pow,\n        separator = /[, ]+/,\n        eve = R.eve,\n        E = \"\",\n        S = \" \";\n    var xlink = \"http://www.w3.org/1999/xlink\",\n        markers = {\n            block: \"M5,0 0,2.5 5,5z\",\n            classic: \"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",\n            diamond: \"M2.5,0 5,2.5 2.5,5 0,2.5z\",\n            open: \"M6,1 1,3.5 6,6\",\n            oval: \"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"\n        },\n        markerCounter = {};\n    R.toString = function () {\n        return  \"Your browser supports SVG.\\nYou are running Rapha\\xebl \" + this.version;\n    };\n    var $ = function (el, attr) {\n        if (attr) {\n            if (typeof el == \"string\") {\n                el = $(el);\n            }\n            for (var key in attr) if (attr[has](key)) {\n                if (key.substring(0, 6) == \"xlink:\") {\n                    el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));\n                } else {\n                    el.setAttribute(key, Str(attr[key]));\n                }\n            }\n        } else {\n            el = R._g.doc.createElementNS(\"http://www.w3.org/2000/svg\", el);\n            el.style && (el.style.webkitTapHighlightColor = \"rgba(0,0,0,0)\");\n        }\n        return el;\n    },\n    addGradientFill = function (element, gradient) {\n        var type = \"linear\",\n            id = element.id + gradient,\n            fx = .5, fy = .5,\n            o = element.node,\n            SVG = element.paper,\n            s = o.style,\n            el = R._g.doc.getElementById(id);\n        if (!el) {\n            gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {\n                type = \"radial\";\n                if (_fx && _fy) {\n                    fx = toFloat(_fx);\n                    fy = toFloat(_fy);\n                    var dir = ((fy > .5) * 2 - 1);\n                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&\n                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&\n                        fy != .5 &&\n                        (fy = fy.toFixed(5) - 1e-5 * dir);\n                }\n                return E;\n            });\n            gradient = gradient.split(/\\s*\\-\\s*/);\n            if (type == \"linear\") {\n                var angle = gradient.shift();\n                angle = -toFloat(angle);\n                if (isNaN(angle)) {\n                    return null;\n                }\n                var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],\n                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);\n                vector[2] *= max;\n                vector[3] *= max;\n                if (vector[2] < 0) {\n                    vector[0] = -vector[2];\n                    vector[2] = 0;\n                }\n                if (vector[3] < 0) {\n                    vector[1] = -vector[3];\n                    vector[3] = 0;\n                }\n            }\n            var dots = R._parseDots(gradient);\n            if (!dots) {\n                return null;\n            }\n            id = id.replace(/[\\(\\)\\s,\\xb0#]/g, \"_\");\n\n            if (element.gradient && id != element.gradient.id) {\n                SVG.defs.removeChild(element.gradient);\n                delete element.gradient;\n            }\n\n            if (!element.gradient) {\n                el = $(type + \"Gradient\", {id: id});\n                element.gradient = el;\n                $(el, type == \"radial\" ? {\n                    fx: fx,\n                    fy: fy\n                } : {\n                    x1: vector[0],\n                    y1: vector[1],\n                    x2: vector[2],\n                    y2: vector[3],\n                    gradientTransform: element.matrix.invert()\n                });\n                SVG.defs.appendChild(el);\n                for (var i = 0, ii = dots.length; i < ii;
57601 i++) {\n                    el.appendChild($(\"stop\", {\n                        offset: dots[i].offset ? dots[i].offset : i ? \"100%\" : \"0%\",\n                        \"stop-color\": dots[i].color || \"#fff\",\n                        \"stop-opacity\": isFinite(dots[i].opacity) ? dots[i].opacity : 1\n                    }));\n                }\n            }\n        }\n        $(o, {\n            fill: fillurl(id),\n            opacity: 1,\n            \"fill-opacity\": 1\n        });\n        s.fill = E;\n        s.opacity = 1;\n        s.fillOpacity = 1;\n        return 1;\n    },\n    isIE9or10 = function () {\n      var mode = document.documentMode;\n      return mode && (mode === 9 || mode === 10);\n    },\n    fillurl = function (id) {\n      if (isIE9or10()) {\n          return \"url('#\" + id + \"')\";\n      }\n      var location = document.location;\n      var locationString = (\n          location.protocol + '//' +\n          location.host +\n          location.pathname +\n          location.search\n      );\n      return \"url('\" + locationString + \"#\" + id + \"')\";\n    },\n    updatePosition = function (o) {\n        var bbox = o.getBBox(1);\n        $(o.pattern, {patternTransform: o.matrix.invert() + \" translate(\" + bbox.x + \",\" + bbox.y + \")\"});\n    },\n    addArrow = function (o, value, isEnd) {\n        if (o.type == \"path\") {\n            var values = Str(value).toLowerCase().split(\"-\"),\n                p = o.paper,\n                se = isEnd ? \"end\" : \"start\",\n                node = o.node,\n                attrs = o.attrs,\n                stroke = attrs[\"stroke-width\"],\n                i = values.length,\n                type = \"classic\",\n                from,\n                to,\n                dx,\n                refX,\n                attr,\n                w = 3,\n                h = 3,\n                t = 5;\n            while (i--) {\n                switch (values[i]) {\n                    case \"block\":\n                    case \"classic\":\n                    case \"oval\":\n                    case \"diamond\":\n                    case \"open\":\n                    case \"none\":\n                        type = values[i];\n                        break;\n                    case \"wide\": h = 5; break;\n                    case \"narrow\": h = 2; break;\n                    case \"long\": w = 5; break;\n                    case \"short\": w = 2; break;\n                }\n            }\n            if (type == \"open\") {\n                w += 2;\n                h += 2;\n                t += 2;\n                dx = 1;\n                refX = isEnd ? 4 : 1;\n                attr = {\n                    fill: \"none\",\n                    stroke: attrs.stroke\n                };\n            } else {\n                refX = dx = w / 2;\n                attr = {\n                    fill: attrs.stroke,\n                    stroke: \"none\"\n                };\n            }\n            if (o._.arrows) {\n                if (isEnd) {\n                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;\n                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;\n                } else {\n                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;\n                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;\n                }\n            } else {\n                o._.arrows = {};\n            }\n            if (type != \"none\") {\n                var pathId = \"raphael-marker-\" + type,\n                    markerId = \"raphael-marker-\" + se + type + w + h + \"-obj\" + o.id;\n                if (!R._g.doc.getElementById(pathId)) {\n                    p.defs.appendChild($($(\"path\"), {\n                        \"stroke-linecap\": \"round\",\n                        d: markers[type],\n                        id: pathId\n                    }));\n                    markerCounter[pathId] = 1;\n                } else {\n                    markerCounter[pathId]++;\n                }\n                var marker = R._g.doc.getElementById(markerId),\n                    use;\n                if (!marker) {\n                    marker = $($(\"marker\"), {\n                        id: markerId,\n                        markerHeight: h,\n                        markerWidth: w,\n                        orient: \"auto\",\n                        refX: refX,\n                        refY: h / 2\n                    });\n                    use = $($(\"use\"), {\n                        \"xlink:href\": \"#\" + pathId,\n                        transform: (isEnd ? \"rotate(180 \" + w / 2 + \" \" + h / 2 + \") \" : E) + \"scale(\" + w / t + \",\" + h / t + \")\",\n                        \"stroke-width\": (1 / ((w / t + h / t) / 2)).toFixed(4)\n                    });\n                    marker.appendChild(use);\n                    p.defs.appendChild(marker);\n                    markerCounter[markerId] = 1;\n                } else {\n                    markerCounter[markerId]++;\n                    use = marker.getElementsByTagName(\"use\")[0];\n                }\n                $(use, attr);\n                var delta = dx * (type != \"diamond\" && type != \"oval\");\n                if (isEnd) {\n                    from = o._.arrows.startdx * stroke || 0;\n                    to = R.getTotalLength(attrs.path) - delta * stroke;\n                } else {\n                    from = delta * stroke;\n                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n                }\n                attr = {};\n                attr[\"marker-\" + se] = \"url(#\" + markerId + \")\";\n                if (to || from) {\n                    attr.d = R.getSubpath(attrs.path, from, to);\n                }\n                $(node, attr);\n                o._.arrows[se + \"Path\"] = pathId;\n                o._.arrows[se + \"Marker\"] = markerId;\n                o._.arrows[se + \"dx\"] = delta;\n                o._.arrows[se + \"Type\"] = type;\n                o._.arrows[se + \"String\"] = value;\n            } else {\n                if (isEnd) {\n                    from = o._.arrows.startdx * stroke || 0;\n                    to = R.getTotalLength(attrs.path) - from;\n                } else {\n                    from = 0;\n                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n                }\n                o._.arrows[se + \"Path\"] && $(node, {d: R.getSubpath(attrs.path, from, to)});\n                delete o._.arrows[se + \"Path\"];\n                delete o._.arrows[se + \"Marker\"];\n                delete o._.arrows[se + \"dx\"];\n                delete o._.arrows[se + \"Type\"];\n                delete o._.arrows[se + \"String\"];\n            }\n            for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {\n                var item = R._g.doc.getElementById(attr);\n                item && item.parentNode.removeChild(item);\n            }\n        }\n    },\n    dasharray = {\n        \"-\": [3, 1],\n        \".\": [1, 1],\n        \"-.\": [3, 1, 1, 1],\n        \"-..\": [3, 1, 1, 1, 1, 1],\n        \". \": [1, 3],\n        \"- \": [4, 3],\n        \"--\": [8, 3],\n        \"- .\": [4, 3, 1, 3],\n        \"--.\": [8, 3, 1, 3],\n        \"--..\": [8, 3, 1, 3, 1, 3]\n    },\n    addDashes = function (o, value, params) {\n        value = dasharray[Str(value).toLowerCase()];\n        if (value) {\n            var width = o.attrs[\"stroke-width\"] || \"1\",\n                butt = {round: width, square: width, butt: 0}[o.attrs[\"stroke-linecap\"] || params[\"stroke-linecap\"]] || 0,\n                dashes = [],\n                i = value.length;\n            while (i--) {\n                dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;\n            }\n            $(o.node, {\"stroke-dasharray\": dashes.join(\",\")});\n        }\n        else {\n          $(o.node, {\"stroke-dasharray\": \"none\"});\n        }\n    },\n    setFillAndStroke = function (o, params) {\n        var node = o.node,\n            attrs = o.attrs,\n            vis = node.style.visibility;\n        node.style.visibility = \"hidden\";\n        for (var att in params) {\n            if (params[has](att)) {\n                if (!R._availableAttrs[has](att)) {\n                    continue;\n                }\n                var value = params[att];\n                attrs[att] = value;\n                switch (att) {\n                    case \"blur\":\n                        o.blur(value);\n                        break;\n                    case \"title\":\n                        var title = node.getElementsByTagName(\"title\");\n\n                        // Use the existing <title>.\n                        if (title.length && (title = title[0])) {\n                          title.firstChild.nodeValue = value;\n                        } else {\n                          title = $(\"title\");\n                          var val = R._g.doc.createTextNode(value);\n                          title.appendChild(val);\n                          node.appendChild(title);\n                        }\n                        break;\n                    case \"href\":\n                    case \"target\":\n                        var pn = node.parentNode;\n                        if (pn.tagName.toLowerCase() != \"a\") {\n                            var hl = $(\"a\");\n                            pn.insertBefore(hl, node);\n                            hl.appendChild(node);\n                            pn = hl;\n                        }\n                        if (att == \"target\") {\n                            pn.setAttributeNS(xlink, \"show\", value == \"blank\" ? \"new\" : value);\n                        } else {\n                            pn.setAttributeNS(xlink, att, value);\n                        }\n                        break;\n                    case \"cursor\":\n                        node.style.cursor = value;\n                        break;\n                    case \"transform\":\n                        o.transform(value);\n                        break;\n                    case \"arrow-start\":\n                        addArrow(o, value);\n                        break;\n                    case \"arrow-end\":\n                        addArrow(o, value, 1);\n                        break;\n                    case \"clip-rect\":\n                        var rect = Str(value).split(separator);\n                        if (rect.length == 4) {\n                            o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);\n                            var el = $(\"clipPath\"),\n                                rc = $(\"rect\");\n                            el.id = R.createUUID();\n                            $(rc, {\n                                x: rect[0],\n                                y: rect[1],\n                                width: rect[2],\n                                height: rect[3]\n                            });\n                            el.appendChild(rc);\n                            o.paper.defs.appendChild(el);\n                            $(node, {\"clip-path\": \"url(#\" + el.id + \")\"});\n                            o.clip = rc;\n                        }\n                        if (!value) {\n                            var path = node.getAttribute(\"clip-path\");\n                            if (path) {\n                                var clip = R._g.doc.getElementById(path.replace(/(^url\\(#|\\)$)/g, E));\n                                clip && clip.parentNode.removeChild(clip);\n                                $(node, {\"clip-path\": E});\n                                delete o.clip;\n                            }\n                        }\n                    break;\n                    case \"path\":\n                        if (o.type == \"path\") {\n                            $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : \"M0,0\"});\n                            o._.dirty = 1;\n                            if (o._.arrows) {\n                                \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n                                \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n                            }\n                        }\n                        break;\n                    case \"width\":\n                        node.setAttribute(att, value);\n                        o._.dirty = 1;\n                        if (attrs.fx) {\n                            att = \"x\";\n                            value = attrs.x;\n                        } else {\n                            break;\n                        }\n                    case \"x\":\n                        if (attrs.fx) {\n                            value = -attrs.x - (attrs.width || 0);\n                        }\n                    case \"rx\":\n                        if (att == \"rx\" && o.type == \"rect\") {\n                            break;\n                        }\n                    case \"cx\":\n                        node.setAttribute(att, value);\n                        o.pattern && updatePosition(o);\n                        o._.dirty = 1;\n                        break;
57601\n                    case \"height\":\n                        node.setAttribute(att, value);\n                        o._.dirty = 1;\n                        if (attrs.fy) {\n                            att = \"y\";\n                            value = attrs.y;\n                        } else {\n                            break;\n                        }\n                    case \"y\":\n                        if (attrs.fy) {\n                            value = -attrs.y - (attrs.height || 0);\n                        }\n                    case \"ry\":\n                        if (att == \"ry\" && o.type == \"rect\") {\n                            break;\n                        }\n                    case \"cy\":\n                        node.setAttribute(att, value);\n                        o.pattern && updatePosition(o);\n                        o._.dirty = 1;\n                        break;\n                    case \"r\":\n                        if (o.type == \"rect\") {\n                            $(node, {rx: value, ry: value});\n                        } else {\n                            node.setAttribute(att, value);\n                        }\n                        o._.dirty = 1;\n                        break;\n                    case \"src\":\n                        if (o.type == \"image\") {\n                            node.setAttributeNS(xlink, \"href\", value);\n                        }\n                        break;\n                    case \"stroke-width\":\n                        if (o._.sx != 1 || o._.sy != 1) {\n                            value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;\n                        }\n                        node.setAttribute(att, value);\n                        if (attrs[\"stroke-dasharray\"]) {\n                            addDashes(o, attrs[\"stroke-dasharray\"], params);\n                        }\n                        if (o._.arrows) {\n                            \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n                            \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n                        }\n                        break;\n                    case \"stroke-dasharray\":\n                        addDashes(o, value, params);\n                        break;\n                    case \"fill\":\n                        var isURL = Str(value).match(R._ISURL);\n                        if (isURL) {\n                            el = $(\"pattern\");\n                            var ig = $(\"image\");\n                            el.id = R.createUUID();\n                            $(el, {x: 0, y: 0, patternUnits: \"userSpaceOnUse\", height: 1, width: 1});\n                            $(ig, {x: 0, y: 0, \"xlink:href\": isURL[1]});\n                            el.appendChild(ig);\n\n                            (function (el) {\n                                R._preload(isURL[1], function () {\n                                    var w = this.offsetWidth,\n                                        h = this.offsetHeight;\n                                    $(el, {width: w, height: h});\n                                    $(ig, {width: w, height: h});\n                                });\n                            })(el);\n                            o.paper.defs.appendChild(el);\n                            $(node, {fill: \"url(#\" + el.id + \")\"});\n                            o.pattern = el;\n                            o.pattern && updatePosition(o);\n                            break;\n                        }\n                        var clr = R.getRGB(value);\n                        if (!clr.error) {\n                            delete params.gradient;\n                            delete attrs.gradient;\n                            !R.is(attrs.opacity, \"undefined\") &&\n                                R.is(params.opacity, \"undefined\") &&\n                                $(node, {opacity: attrs.opacity});\n                            !R.is(attrs[\"fill-opacity\"], \"undefined\") &&\n                                R.is(params[\"fill-opacity\"], \"undefined\") &&\n                                $(node, {\"fill-opacity\": attrs[\"fill-opacity\"]});\n                        } else if ((o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value)) {\n                            if (\"opacity\" in attrs || \"fill-opacity\" in attrs) {\n                                var gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n                                if (gradient) {\n                                    var stops = gradient.getElementsByTagName(\"stop\");\n                                    $(stops[stops.length - 1], {\"stop-opacity\": (\"opacity\" in attrs ? attrs.opacity : 1) * (\"fill-opacity\" in attrs ? attrs[\"fill-opacity\"] : 1)});\n                                }\n                            }\n                            attrs.gradient = value;\n                            attrs.fill = \"none\";\n                            break;\n                        }\n                        clr[has](\"opacity\") && $(node, {\"fill-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n                    case \"stroke\":\n                        clr = R.getRGB(value);\n                        node.setAttribute(att, clr.hex);\n                        att == \"stroke\" && clr[has](\"opacity\") && $(node, {\"stroke-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n                        if (att == \"stroke\" && o._.arrows) {\n                            \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n                            \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n                        }\n                        break;\n                    case \"gradient\":\n                        (o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value);\n                        break;\n                    case \"opacity\":\n                        if (attrs.gradient && !attrs[has](\"stroke-opacity\")) {\n                            $(node, {\"stroke-opacity\": value > 1 ? value / 100 : value});\n                        }\n                        // fall\n                    case \"fill-opacity\":\n                        if (attrs.gradient) {\n                            gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n                            if (gradient) {\n                                stops = gradient.getElementsByTagName(\"stop\");\n                                $(stops[stops.length - 1], {\"stop-opacity\": value});\n                            }\n                            break;\n                        }\n                    default:\n                        att == \"font-size\" && (value = toInt(value, 10) + \"px\");\n                        var cssrule = att.replace(/(\\-.)/g, function (w) {\n                            return w.substring(1).toUpperCase();\n                        });\n                        node.style[cssrule] = value;\n                        o._.dirty = 1;\n                        node.setAttribute(att, value);\n                        break;\n                }\n            }\n        }\n\n        tuneText(o, params);\n        node.style.visibility = vis;\n    },\n    leading = 1.2,\n    tuneText = function (el, params) {\n        if (el.type != \"text\" || !(params[has](\"text\") || params[has](\"font\") || params[has](\"font-size\") || params[has](\"x\") || params[has](\"y\"))) {\n            return;\n        }\n        var a = el.attrs,\n            node = el.node,\n            fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue(\"font-size\"), 10) : 10;\n\n        if (params[has](\"text\")) {\n            a.text = params.text;\n            while (node.firstChild) {\n                node.removeChild(node.firstChild);\n            }\n            var texts = Str(params.text).split(\"\\n\"),\n                tspans = [],\n                tspan;\n            for (var i = 0, ii = texts.length; i < ii;
57601 i++) {\n                tspan = $(\"tspan\");\n                i && $(tspan, {dy: fontSize * leading, x: a.x});\n                tspan.appendChild(R._g.doc.createTextNode(texts[i]));\n                node.appendChild(tspan);\n                tspans[i] = tspan;\n            }\n        } else {\n            tspans = node.getElementsByTagName(\"tspan\");\n            for (i = 0, ii = tspans.length; i < ii; i++) if (i) {\n                $(tspans[i], {dy: fontSize * leading, x: a.x});\n            } else {\n                $(tspans[0], {dy: 0});\n            }\n        }\n        $(node, {x: a.x, y: a.y});\n        el._.dirty = 1;\n        var bb = el._getBBox(),\n            dif = a.y - (bb.y + bb.height / 2);\n        dif && R.is(dif, \"finite\") && $(tspans[0], {dy: dif});\n    },\n    getRealNode = function (node) {\n        if (node.parentNode && node.parentNode.tagName.toLowerCase() === \"a\") {\n            return node.parentNode;\n        } else {\n            return node;\n        }\n    },\n    Element = function (node, svg) {\n        var X = 0,\n            Y = 0;\n        /*\\\n         * Element.node\n         [ property (object) ]\n         **\n         * Gives you a reference to the DOM object, so you can assign event handlers or just mess around.\n         **\n         * Note: Don’t mess with it.\n         > Usage\n         | // draw a circle at coordinate 10,10 with radius of 10\n         | var c = paper.circle(10, 10, 10);\n         | c.node.onclick = function () {\n         |     c.attr(\"fill\", \"red\");\n         | };\n        \\*/\n        this[0] = this.node = node;\n        /*\\\n         * Element.raphael\n         [ property (object) ]\n         **\n         * Internal reference to @Raphael object. In case it is not available.\n         > Usage\n         | Raphael.el.red = function () {\n         |     var hsb = this.paper.raphael.rgb2hsb(this.attr(\"fill\"));\n         |     hsb.h = 1;\n         |     this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});\n         | }\n        \\*/\n        node.raphael = true;\n        /*\\\n         * Element.id\n         [ property (number) ]\n         **\n         * Unique id of the element. Especially useful when you want to listen to events of the element,\n         * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method.\n        \\*/\n        this.id = guid();\n        node.raphaelid = this.id;\n\n        /**\n        * Method that returns a 5 letter/digit id, enough for 36^5 = 60466176 elements\n        * @returns {string} id\n        */\n        function guid() {\n            return (\"0000\" + (Math.random()*Math.pow(36,5) << 0).toString(36)).slice(-5);\n        }\n\n        this.matrix = R.matrix();\n        this.realPath = null;\n        /*\\\n         * Element.paper\n         [ property (object) ]\n         **\n         * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions.\n         > Usage\n         | Raphael.el.cross = function () {\n         |     this.attr({fill: \"red\"});\n         |     this.paper.path(\"M10,10L50,50M50,10L10,50\")\n         |         .attr({stroke: \"red\"});\n         | }\n        \\*/\n        this.paper = svg;\n        this.attrs = this.attrs || {};\n        this._ = {\n            transform: [],\n            sx: 1,\n            sy: 1,\n            deg: 0,\n            dx: 0,\n            dy: 0,\n            dirty: 1\n        };\n        !svg.bottom && (svg.bottom = this);\n        /*\\\n         * Element.prev\n         [ property (object) ]\n         **\n         * Reference to the previous element in the hierarchy.\n        \\*/\n        this.prev = svg.top;\n        svg.top && (svg.top.next = this);\n        svg.top = this;\n        /*\\\n         * Element.next\n         [ property (object) ]\n         **\n         * Reference to the next element in the hierarchy.\n        \\*/\n        this.next = null;\n    },\n    elproto = R.el;\n\n    Element.prototype = elproto;\n    elproto.constructor = Element;\n\n    R._engine.path = function (pathString, SVG) {\n        var el = $(\"path\");\n        SVG.canvas && SVG.canvas.appendChild(el);\n        var p = new Element(el, SVG);\n        p.type = \"path\";\n        setFillAndStroke(p, {\n            fill: \"none\",\n            stroke: \"#000\",\n            path: pathString\n        });\n        return p;\n    };\n    /*\\\n     * Element.rotate\n     [ method ]\n     **\n     * Deprecated! Use @Element.transform instead.\n     * Adds rotation by given angle around given point to the list of\
57601n     * transformations of the element.\n     > Parameters\n     - deg (number) angle in degrees\n     - cx (number) #optional x coordinate of the centre of rotation\n     - cy (number) #optional y coordinate of the centre of rotation\n     * If cx & cy aren’t specified centre of the shape is used as a point of rotation.\n     = (object) @Element\n    \\*/\n    elproto.rotate = function (deg, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        deg = Str(deg).split(separator);\n        if (deg.length - 1) {\n            cx = toFloat(deg[1]);\n            cy = toFloat(deg[2]);\n        }\n        deg = toFloat(deg[0]);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n            cx = bbox.x + bbox.width / 2;\n            cy = bbox.y + bbox.height / 2;\n        }\n        this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n        return this;\n    };\n    /*\\\n     * Element.scale\n     [ method ]\n     **\n     * Deprecated! Use @Element.transform instead.\n     * Adds scale by given amount relative to given point to the list of\n     * transformations of the element.\n     > Parameters\n     - sx (number) horisontal scale amount\n     - sy (number) vertical scale amount\n     - cx (number) #optional x coordinate of the centre of scale\n     - cy (number) #optional y coordinate of the centre of scale\n     * If cx & cy aren’t specified centre of the shape is used instead.\n     = (object) @Element\n    \\*/\n    elproto.scale = function (sx, sy, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        sx = Str(sx).split(separator);\n        if (sx.length - 1) {\n            sy = toFloat(sx[1]);\n            cx = toFloat(sx[2]);\n            cy = toFloat(sx[3]);\n        }\n        sx = toFloat(sx[0]);\n        (sy == null) && (sy = sx);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n        }\n        cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n        cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n        this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n        return this;\n    };\n    /*\\\n     * Element.translate\n     [ method ]\n     **\n     * Deprecated! Use @Element.transform instead.\n     * Adds translation by given amount to the list of transformations of the element.\n     > Parameters\n     - dx (number) horisontal shift\n     - dy (number) vertical shift\n     = (object) @Element\n    \\*/\n    elproto.translate = function (dx, dy) {\n        if (this.removed) {\n            return this;\n        }\n        dx = Str(dx).split(separator);\n        if (dx.length - 1) {\n            dy = toFloat(dx[1]);\n        }\n        dx = toFloat(dx[0]) || 0;\n        dy = +dy || 0;\n        this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n        return this;\n    };\n    /*\\\n     * Element.transform\n     [ method ]\n     **\n     * Adds transformation to the element which is separate to other attributes,\n     * i.e. translation doesn’t change `x` or `y` of the rectange. The format\n     * of transformation string is similar to the path string syntax:\n     | \"t100,100r30,100,100s2,2,100,100r45s1.5\"\n     * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for\n     * scale and `m` is for matrix.\n     *\n     * There are also alternative “absolute” translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`.\n     *\n     * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;\n     * rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin\n     * coordinates as optional parameters, the default is the centre point of the element.\n     * Matrix accepts six parameters.\n     > Usage\n     | var el = paper.rect(10, 20, 300, 200);\n     | // translate 100, 100, rotate 45°, translate -100, 0\n     | el.transform(\"t100,100r45t-100,0\");\n     | // if you want you can append or prepend transformations\n     | el.transform(\"...t50,50\");\n     | el.transform(\"s2...\");\n     | // or even wrap\n     | el.transform(\"t50,50...t-50-50\");\n     | // to reset transformation call method with empty string\n     | el.transform(\"\");\n     | // to get current value call it without parameters\n     | console.log(el.transform());\n     > Parameters\n     - tstr (string) #optional transformation string\n     * If tstr isn’t specified\n     = (string) current transformation string\n     * else\n     = (object) @Element\n    \\*/\n    elproto.transform = function (tstr) {\n        var _ = this._;\n        if (tstr == null) {\n            return _.transform;\n        }\n        R._extractTransform(this, tstr);\n\n        this.clip && $(this.clip, {transform: this.matrix.invert()});\n        this.pattern && updatePosition(this);\n        this.node && $(this.node, {transform: this.matrix});\n\n        if (_.sx != 1 || _.sy != 1) {\n            var sw = this.attrs[has](\"stroke-width\") ? this.attrs[\"stroke-width\"] : 1;\n            this.attr({\"stroke-width\": sw}
57601);\n        }\n\n        return this;\n    };\n    /*\\\n     * Element.hide\n     [ method ]\n     **\n     * Makes element invisible. See @Element.show.\n     = (object) @Element\n    \\*/\n    elproto.hide = function () {\n        if(!this.removed) this.node.style.display = \"none\";\n        return this;\n    };\n    /*\\\n     * Element.show\n     [ method ]\n     **\n     * Makes element visible. See @Element.hide.\n     = (object) @Element\n    \\*/\n    elproto.show = function () {\n        if(!this.removed) this.node.style.display = \"\";\n        return this;\n    };\n    /*\\\n     * Element.remove\n     [ method ]\n     **\n     * Removes element from the paper.\n    \\*/\n    elproto.remove = function () {\n        var node = getRealNode(this.node);\n        if (this.removed || !node.parentNode) {\n            return;\n        }\n        var paper = this.paper;\n        paper.__set__ && paper.__set__.exclude(this);\n        eve.unbind(\"raphael.*.*.\" + this.id);\n        if (this.gradient) {\n            paper.defs.removeChild(this.gradient);\n        }\n        R._tear(this, paper);\n\n        node.parentNode.removeChild(node);\n\n        // Remove custom data for element\n        this.removeData();\n\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n        this.removed = true;\n    };\n    elproto._getBBox = function () {\n        if (this.node.style.display == \"none\") {\n            this.show();\n            var hide = true;\n        }\n        var canvasHidden = false,\n            containerStyle;\n        if (this.paper.canvas.parentElement) {\n          containerStyle = this.paper.canvas.parentElement.style;\n        } //IE10+ can't find parentElement\n        else if (this.paper.canvas.parentNode) {\n          containerStyle = this.paper.canvas.parentNode.style;\n        }\n\n        if(containerStyle && containerStyle.display == \"none\") {\n          canvasHidden = true;\n          containerStyle.display = \"\";\n        }\n        var bbox = {};\n        try {\n            bbox = this.node.getBBox();\n        } catch(e) {\n            // Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix\n            bbox = {\n                x: this.node.clientLeft,\n                y: this.node.clientTop,\n                width: this.node.clientWidth,\n                height: this.node.clientHeight\n            }\n        } finally {\n            bbox = bbox || {};\n            if(canvasHidden){\n              containerStyle.display = \"none\";\n            }\n        }\n        hide && this.hide();\n        return bbox;\n    };\n    /*\\\n     * Element.attr\n     [ method ]\n     **\n     * Sets the attributes of the element.\n     > Parameters\n     - attrName (string) attribute’s name\n     - value (string) value\n     * or\n     - params (object) object of name/value pairs\n     * or\n     - attrName (string) attribute’s name\n     * or\n     - attrNames (array) in this case method returns array of current values for given attribute names\n     = (object) @Element if attrsName & value or params are passed in.\n     = (...) value of the attribute if only attrsName is passed in.\n     = (array) array of values of the attribute if attrsNames is passed in.\n     = (object) object of attributes if nothing is passed in.\n     > Possible parameters\n     # <p>Please refer to the <a href=\"http://www.w3.org/TR/SVG/\" title=\"The W3C Recommendation for the SVG language describes these properties in detail.\">SVG specification</a> for an explanation of these parameters.</p>\n     o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`.\n     o clip-rect (string) comma or space separated values: x, y, width and height\n     o cursor (string) CSS type of the cursor\n     o cx (number) the x-axis coordinate of the center of the circle, or ellipse\n     o cy (number) the y-axis coordinate of the center of the circle, or ellipse\n     o fill (string) colour, gradient or image\n     o fill-opacity (number)\n     o font (string)\n     o font-family (string)\n     o font-size (number) font size in pixels\n     o font-weight (string)\n     o height (number)\n     o href (string) URL, if specified element behaves as hyperlink\n     o opacity (number)\n     o path (string) SVG path string format\n     o r (number) radius of the circle, ellipse or rounded corner on the rect\n     o rx (number) horisontal radius of the ellipse\n     o ry (number) vertical radius of the ellipse\n     o src (string) image URL, only works for @Element.image element\n     o stroke (string) stroke colour\n     o stroke-dasharray (string) [“”, “none”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”]\n     o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”]\n     o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”]\n     o stroke-miterlimit (number)\n     o stroke-opacity (number)\n     o stroke-width (number) stroke width in pixels, default is '1'\n     o target (string) used with href\n     o text (string) contents of the text element. Use `\\n` for multiline text\n     o text-anchor (string) [“`start`”, “`middle`”, “`end`â€
57601], default is “`middle`”\n     o title (string) will create tooltip with a given text\n     o transform (string) see @Element.transform\n     o width (number)\n     o x (number)\n     o y (number)\n     > Gradients\n     * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90°\n     * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black.\n     *\n     * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” –\n     * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point\n     * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.\n     > Path String\n     # <p>Please refer to <a href=\"http://www.w3.org/TR/SVG/paths.html#PathData\" title=\"Details of a path’s data attribute’s format are described in the SVG specification.\">SVG documentation regarding path string</a>. Raphaël fully supports it.</p>\n     > Colour Parsing\n     # <ul>\n     #     <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>\n     #     <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>\n     #     <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>\n     #     <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>\n     #     <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>\n     #     <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(200,&nbsp;100,&nbsp;0, .5)</code>”)</li>\n     #     <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%,&nbsp;175%,&nbsp;0%, 50%)</code>”)</li>\n     #     <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>\n     #     <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>\n     #     <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li>\n     #     <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href=\"http://en.wikipedia.org/wiki/HSL_and_HSV\" title=\"HSL and HSV - Wikipedia, the free encyclopedia\">Wikipedia page</a></li>\n     #     <li>hsl(•••%, •••%, •••%) — same as above, but in %</li>\n     #     <li>hsla(•••, •••, •••, •••) — same as above, but with opacity</li>\n     #     <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg,&nbsp;1,&nbsp;.5)</code>” or, if you want to go fancy, “<code>hsl(240°,&nbsp;1,&nbsp;.5)</code>”</li>\n     # </ul>\n    \\*/\n    elproto.attr = function (name, value) {\n        if (this.removed) {\n            return this;\n        }\n        if (name == null) {\n            var res = {};\n            for (var a in this.attrs) if (this.attrs[has](a)) {\n                res[a] = this.attrs[a];\n            }\n            res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n            res.transform = this._.transform;\n            return res;\n        }\n        if (value == null && R.is(name, \"string\")) {\n            if (name == \"fill\" && this.attrs.fill == \"none\" && this.attrs.gradient) {\n                return this.attrs.gradient;\n            }\n            if (name == \"transform\") {\n                return this._.transform;\n            }\n            var names = name.split(separator),\n                out = {};\n            for (var i = 0, ii = names.length; i < ii;
57601 i++) {\n                name = names[i];\n                if (name in this.attrs) {\n                    out[name] = this.attrs[name];\n                } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n                    out[name] = this.paper.customAttributes[name].def;\n                } else {\n                    out[name] = R._availableAttrs[name];\n                }\n            }\n            return ii - 1 ? out : out[names[0]];\n        }\n        if (value == null && R.is(name, \"array\")) {\n            out = {};\n            for (i = 0, ii = name.length; i < ii; i++) {\n                out[name[i]] = this.attr(name[i]);\n            }\n            return out;\n        }\n        if (value != null) {\n            var params = {};\n            params[name] = value;\n        } else if (name != null && R.is(name, \"object\")) {\n            params = name;\n        }\n        for (var key in params) {\n            eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n        }\n        for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n            var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n            this.attrs[key] = params[key];\n            for (var subkey in par) if (par[has](subkey)) {\n                params[subkey] = par[subkey];\n            }\n        }\n        setFillAndStroke(this, params);\n        return this;\n    };\n    /*\\\n     * Element.toFront\n     [ method ]\n     **\n     * Moves the element so it is the closest to the viewer’s eyes, on top of other elements.\n     = (object) @Element\n    \\*/\n    elproto.toFront = function () {\n        if (this.removed) {\n            return this;\n        }\n        var node = getRealNode(this.node);\n        node.parentNode.appendChild(node);\n        var svg = this.paper;\n        svg.top != this && R._tofront(this, svg);\n        return this;\n    };\n    /*\\\n     * Element.toBack\n     [ method ]\n     **\n     * Moves the element so it is the furthest from the viewer’s eyes, behind other elements.\n     = (object) @Element\n    \\*/\n    elproto.toBack = function () {\n        if (this.removed) {\n            return this;\n        }\n        var node = getRealNode(this.node);\n        var parentNode = node.parentNode;\n        parentNode.insertBefore(node, parentNode.firstChild);\n        R._toback(this, this.paper);\n        var svg = this.paper;\n        return this;\n    };\n    /*\\\n     * Element.insertAfter\n     [ method ]\n     **\n     * Inserts current object after the given one.\n     = (object) @Element\n    \\*/\n    elproto.insertAfter = function (element) {\n        if (this.removed || !element) {\n            return this;\n        }\n\n        var node = getRealNode(this.node);\n        var afterNode = getRealNode(element.node || element[element.length - 1].node);\n        if (afterNode.nextSibling) {\n            afterNode.parentNode.insertBefore(node, afterNode.nextSibling);\n        } else {\n            afterNode.parentNode.appendChild(node);\n        }\n        R._insertafter(this, element, this.paper);\n        return this;\n    };\n    /*\\\n     * Element.insertBefore\n     [ method ]\n     **\n     * Inserts current object before the given one.\n     = (object) @Element\n    \\*/\n    elproto.insertBefore = function (element) {\n        if (this.removed || !element) {\n            return this;\n        }\n\n        var node = getRealNode(this.node);\n        var beforeNode = getRealNode(element.node || element[0].node);\n        beforeNode.parentNode.insertBefore(node, beforeNode);\n        R._insertbefore(this, element, this.paper);\n        return this;\n    };\n    elproto.blur = function (size) {\n        // Experimental. No Safari support. Use it on your own risk.\n        var t = this;\n        if (+size !== 0) {\n            var fltr = $(\"filter\"),\n                blur = $(\"feGaussianBlur\");\n            t.attrs.blur = size;\n            fltr.id = R.createUUID();\n            $(blur, {stdDeviation: +size || 1.5});\n            fltr.appendChild(blur);\n            t.paper.defs.appendChild(fltr);\n            t._blur = fltr;\n            $(t.node, {filter: \"url(#\" + fltr.id + \")\"});\n        } else {\n            if (t._blur) {\n                t._blur.parentNode.removeChild(t._blur);\n                delete t._blur;\n                delete t.attrs.blur;\n            }\n            t.node.removeAttribute(\"filter\");\n        }\n        return t;\n    };\n    R._engine.circle = function (svg, x, y, r) {\n        var el = $(\"circle\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {cx: x, cy: y, r: r, fill: \"none\", stroke: \"#000\"};\n        res.type = \"circle\";\n        $(el, res.attrs);\n        return res;\n    };\n    R._engine.rect = function (svg, x, y, w, h, r) {\n        var el = $(\"rect\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {x: x, y: y, width: w, height: h, rx: r || 0, ry: r || 0, fill: \"none\", stroke: \"#000\"};\n        res.type = \"rect\";\n        $(el, res.attrs);\n        return res;\n    };\n    R._engine.ellipse = function (svg, x, y, rx, ry) {\n        var el = $(\"ellipse\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: \"none\", stroke: \"#000\"};\n        res.type = \"ellipse\";\n        $(el, res.attrs);\n        return res;\n    };\n    R._engine.image = function (svg, src, x, y, w, h) {\n        var el = $(\"image\");\n        $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: \"none\"});\n        el.setAttributeNS(xlink, \"href\", src);\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {x: x, y: y, width: w, height: h, src: src};\n        res.type = \"image\";\n        return res;\n    };\n    R._engine.text = function (svg, x, y, text) {\n        var el = $(\"text\");\n        svg.canvas && svg.canvas.appendChild(el);\n        var res = new Element(el, svg);\n        res.attrs = {\n            x: x,\n            y: y,\n            \"text-anchor\": \"middle\",\n            text: text,\n            \"font-family\": R._availableAttrs[\"font-family\"],\n            \"font-size\": R._availableAttrs[\"font-size\"],\n            stroke: \"none\",\n            fill: \"#000\"\n        };\n        res.type = \"text\";\n        setFillAndStroke(res, res.attrs);\n        return res;\n    };\n    R._engine.setSize = function (width, height) {\n        this.width = width || this.width;\n        this.height = height || this.height;\n        this.canvas.setAttribute(\"width\", this.width);\n        this.canvas.setAttribute(\"height\", this.height);\n        if (this._viewBox) {\n            this.setViewBox.apply(this, this._viewBox);\n        }\n        return this;\n    };\n    R._engine.create = function () {\n        var con = R._getContainer.apply(0, arguments),\n            container = con && con.container;\n        if (!container) {\n            throw new Error(\"SVG container not found.\");\n        }\n        var x = con.x,\n            y = con.y,\n            width = con.width,\n            height = con.height,\n            cnvs = $(\"svg\"),\n            css = \"overflow:hidden;\",\n            isFloating;\n        x = x || 0;\n        y = y || 0;\n        width = width || 512;\n        height = height || 342;
57601\n        $(cnvs, {\n            height: height,\n            version: 1.1,\n            width: width,\n            xmlns: \"http://www.w3.org/2000/svg\",\n            \"xmlns:xlink\": \"http://www.w3.org/1999/xlink\"\n        });\n        if (container == 1) {\n            cnvs.style.cssText = css + \"position:absolute;left:\" + x + \"px;top:\" + y + \"px\";\n            R._g.doc.body.appendChild(cnvs);\n            isFloating = 1;\n        } else {\n            cnvs.style.cssText = css + \"position:relative\";\n            if (container.firstChild) {\n                container.insertBefore(cnvs, container.firstChild);\n            } else {\n                container.appendChild(cnvs);\n            }\n        }\n        container = new R._Paper;\n        container.width = width;\n        container.height = height;\n        container.canvas = cnvs;\n        container.clear();\n        container._left = container._top = 0;\n        isFloating && (container.renderfix = function () {});\n        container.renderfix();\n        return container;\n    };\n    R._engine.setViewBox = function (x, y, w, h, fit) {\n        eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n        var paperSize = this.getSize(),\n            size = mmax(w / paperSize.width, h / paperSize.height),\n            top = this.top,\n            aspectRatio = fit ? \"xMidYMid meet\" : \"xMinYMin\",\n            vb,\n            sw;\n        if (x == null) {\n            if (this._vbSize) {\n                size = 1;\n            }\n            delete this._vbSize;\n            vb = \"0 0 \" + this.width + S + this.height;\n        } else {\n            this._vbSize = size;\n            vb = x + S + y + S + w + S + h;\n        }
57601\n        $(this.canvas, {\n            viewBox: vb,\n            preserveAspectRatio: aspectRatio\n        });\n        while (size && top) {\n            sw = \"stroke-width\" in top.attrs ? top.attrs[\"stroke-width\"] : 1;\n            top.attr({\"stroke-width\": sw});\n            top._.dirty = 1;\n            top._.dirtyT = 1;\n            top = top.prev;\n        }\n        this._viewBox = [x, y, w, h, !!fit];\n        return this;\n    };\n    /*\\\n     * Paper.renderfix\n     [ method ]\n     **\n     * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependent\n     * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.\n     * This method fixes the issue.\n     **\n       Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.\n    \\*/\n    R.prototype.renderfix = function () {\n        var cnvs = this.canvas,\n            s = cnvs.style,\n            pos;\n        try {\n            pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();\n        } catch (e) {\n            pos = cnvs.createSVGMatrix();\n        }\n        var left = -pos.e % 1,\n            top = -pos.f % 1;\n        if (left || top) {\n            if (left) {\n                this._left = (this._left + left) % 1;\n                s.left = this._left + \"px\";\n            }\n            if (top) {\n                this._top = (this._top + top) % 1;\n                s.top = this._top + \"px\";\n            }\n        }\n    };\n    /*\\\n     * Paper.clear\n     [ method ]\n     **\n     * Clears the paper, i.e. removes all the elements.\n    \\*/\n    R.prototype.clear = function () {\n        R.eve(\"raphael.clear\", this);\n        var c = this.canvas;\n        while (c.firstChild) {\n            c.removeChild(c.firstChild);\n        }\n        this.bottom = this.top = null;\n        (this.desc = $(\"desc\")).appendChild(R._g.doc.createTextNode(\"Created with Rapha\\xebl \" + R.version));\n        c.appendChild(this.desc);\n        c.appendChild(this.defs = $(\"defs\"));\n    };\n    /*\\\n     * Paper.remove\n     [ method ]\n     **\n     * Removes the paper from the DOM.\n    \\*/\n    R.prototype.remove = function () {\n        eve(\"raphael.remove\", this);\n        this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n    };\n    var setproto = R.st;\n    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n        setproto[method] = (function (methodname) {\n            return function () {\n                var arg = arguments;\n                return this.forEach(function (el) {\n                    el[methodname].apply(el, arg);\n                });\n            };\n        })(method);\n    }\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC5zdmcuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SYXBoYWVsLy4vZGV2L3JhcGhhZWwuc3ZnLmpzP2Q4YzciXSwic291cmNlc0NvbnRlbnQiOlsiZGVmaW5lKFtcIi4vcmFwaGFlbC5jb3JlXCJdLCBmdW5jdGlvbihSKSB7XG4gICAgaWYgKFIgJiYgIVIuc3ZnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaGFzID0gXCJoYXNPd25Qcm9wZXJ0eVwiLFxuICAgICAgICBTdHIgPSBTdHJpbmcsXG4gICAgICAgIHRvRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgICB0b0ludCA9IHBhcnNlSW50LFxuICAgICAgICBtYXRoID0gTWF0aCxcbiAgICAgICAgbW1heCA9IG1hdGgubWF4LFxuICAgICAgICBhYnMgPSBtYXRoLmFicyxcbiAgICAgICAgcG93ID0gbWF0aC5wb3csXG4gICAgICAgIHNlcGFyYXRvciA9IC9bLCBdKy8sXG4gICAgICAgIGV2ZSA9IFIuZXZlLFxuICAgICAgICBFID0gXCJcIixcbiAgICAgICAgUyA9IFwiIFwiO1xuICAgIHZhciB4bGluayA9IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiLFxuICAgICAgICBtYXJrZXJzID0ge1xuICAgICAgICAgICAgYmxvY2s6IFwiTTUsMCAwLDIuNSA1LDV6XCIsXG4gICAgICAgICAgICBjbGFzc2ljOiBcIk01LDAgMCwyLjUgNSw1IDMuNSwzIDMuNSwyelwiLFxuICAgICAgICAgICAgZGlhbW9uZDogXCJNMi41LDAgNSwyLjUgMi41LDUgMCwyLjV6XCIsXG4gICAgICAgICAgICBvcGVuOiBcIk02LDEgMSwzLjUgNiw2XCIsXG4gICAgICAgICAgICBvdmFsOiBcIk0yLjUsMEEyLjUsMi41LDAsMCwxLDIuNSw1IDIuNSwyLjUsMCwwLDEsMi41LDB6XCJcbiAgICAgICAgfSxcbiAgICAgICAgbWFya2VyQ291bnRlciA9IHt9O1xuICAgIFIudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgI
57601HJldHVybiAgXCJZb3VyIGJyb3dzZXIgc3VwcG9ydHMgU1ZHLlxcbllvdSBhcmUgcnVubmluZyBSYXBoYVxceGVibCBcIiArIHRoaXMudmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciAkID0gZnVuY3Rpb24gKGVsLCBhdHRyKSB7XG4gICAgICAgIGlmIChhdHRyKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBlbCA9ICQoZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGF0dHIpIGlmIChhdHRyW2hhc10oa2V5KSkge1xuICAgICAgICAgICAgICAgIGlmIChrZXkuc3Vic3RyaW5nKDAsIDYpID09IFwieGxpbms6XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlTlMoeGxpbmssIGtleS5zdWJzdHJpbmcoNiksIFN0cihhdHRyW2tleV0pKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoa2V5LCBTdHIoYXR0cltrZXldKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWwgPSBSLl9nLmRvYy5jcmVhdGVFbGVtZW50TlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLCBlbCk7XG4gICAgICAgICAgICBlbC5zdHlsZSAmJiAoZWwuc3R5bGUud2Via2l0VGFwSGlnaGxpZ2h0Q29sb3IgPSBcInJnYmEoMCwwLDAsMClcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH0sXG4gICAgYWRkR3JhZGllbnRGaWxsID0gZnVuY3Rpb24gKGVsZW1lbnQsIGdyYWRpZW50KSB7XG4gICAgICAgIHZhciB0eXBlID0gXCJsaW5lYXJcIixcbiAgICAgICAgICAgIGlkID0gZWxlbWVudC5pZCArIGdyYWRpZW50LFxuICAgICAgICAgICAgZnggPSAuNSwgZnkgPSAuNSxcbiAgICAgICAgICAgIG8gPSBlbGVtZW50Lm5vZGUsXG4gICAgICAgICAgICBTVkcgPSBlbGVtZW50LnBhcGVyLFxuICAgICAgICAgICAgcyA9IG8uc3R5bGUsXG4gICAgICAgICAgICBlbCA9IFIuX2cuZG9jLmdldEVsZW1lbnRCeUlkKGlkKTtcbiAgICAgICAgaWYgKCFlbCkge1xuICAgICAgICAgICAgZ3JhZGllbnQgPSBTdHIoZ3JhZGllbnQpLnJlcGxhY2UoUi5fcmFkaWFsX2dyYWRpZW50LCBmdW5jdGlvbiAoYWxsLCBfZngsIF9meSkge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBcInJhZGlhbFwiO1xuICAgICAgICAgICAgICAgIGlmIChfZnggJiYgX2Z5KSB7XG4gICAgICAgICAgICAgICAgICAgIGZ4ID0gdG9GbG9hdChfZngpO1xuICAgICAgICAgICAgICAgICAgICBmeSA9IHRvRmxvYXQoX2Z5KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpciA9ICgoZnkgPiAuNSkgKiAyIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIHBvdyhmeCAtIC41LCAyKSArIHBvdyhmeSAtIC41LCAyKSA+IC4yNSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKGZ5ID0gbWF0aC5zcXJ0KC4yNSAtIHBvdyhmeCAtIC41LCAyKSkgKiBkaXIgKyAuNSkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ5ICE9IC41ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoZnkgPSBmeS50b0ZpeGVkKDUpIC0gMWUtNSAqIGRpcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBFO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBncmFkaWVudCA9IGdyYWRpZW50LnNwbGl0KC9cXHMqXFwtXFxzKi8pO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJsaW5lYXJcIikge1xuICAgICAgICAgICAgICAgIHZhciBhbmdsZSA9IGdyYWRpZW50LnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgYW5nbGUgPSAtdG9GbG9hdChhbmdsZSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzTmFOKGFuZ2xlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHZlY3RvciA9IFswLCAwLCBtYXRoLmNvcyhSLnJhZChhbmdsZSkpLCBtYXRoLnNpbihSLnJhZChhbmdsZSkpXSxcbiAgICAgICAgICAgICAgICAgICAgbWF4ID0gMSAvIChtbWF4KGFicyh2ZWN0b3JbMl0pLCBhYnModmVjdG9yWzNdKSkgfHwgMSk7XG4gICAgICAgICAgICAgICAgdmVjdG9yWzJdICo9IG1heDtcbiAgICAgICAgICAgICAgICB2ZWN0b3JbM10gKj0gbWF4O1xuICAgICAgICAgICAgICAgIGlmICh2ZWN0b3JbMl0gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclswXSA9IC12ZWN0b3JbMl07XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclsyXSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh2ZWN0b3JbM10gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclsxXSA9IC12ZWN0b3JbM107XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclszXSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRvdHMgPSBSLl9wYXJzZURvdHMoZ3JhZGllbnQpO1xuICAgICAgICAgICAgaWYgKCFkb3RzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZCA9IGlkLnJlcGxhY2UoL1tcXChcXClcXHMsXFx4YjAjXS9nLCBcIl9cIik7XG5cbiAgICAgICAgICAgIGlmIChlbGVtZW50LmdyYWRpZW50ICYmIGlkICE9IGVsZW1lbnQuZ3JhZGllbnQuaWQpIHtcbiAgICAgICAgICAgICAgICBTVkcuZGVmcy5yZW1vdmVDaGlsZChlbGVtZW50LmdyYWRpZW50KTtcbiAgICAgICAgICAgICAgICBkZWxldGUgZWxlbWVudC5ncmFkaWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFlbGVtZW50LmdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgZWwgPSAkKHR5cGUgKyBcIkdyYWRpZW50XCIsIHtpZDogaWR9KTtcbiAgICAgICAgICAgICAgICBlbGVtZW50LmdyYWRpZW50ID0gZWw7XG4gICAgICAgICAgICAgICAgJChlbCwgdHlwZSA9PSBcInJhZGlhbFwiID8ge1xuICAgICAgICAgICAgICAgICAgICBmeDogZngsXG4gICAgICAgICAgICAgICAgICAgIGZ5OiBmeVxuICAgICAgICAgICAgICAgI
57601H0gOiB7XG4gICAgICAgICAgICAgICAgICAgIHgxOiB2ZWN0b3JbMF0sXG4gICAgICAgICAgICAgICAgICAgIHkxOiB2ZWN0b3JbMV0sXG4gICAgICAgICAgICAgICAgICAgIHgyOiB2ZWN0b3JbMl0sXG4gICAgICAgICAgICAgICAgICAgIHkyOiB2ZWN0b3JbM10sXG4gICAgICAgICAgICAgICAgICAgIGdyYWRpZW50VHJhbnNmb3JtOiBlbGVtZW50Lm1hdHJpeC5pbnZlcnQoKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIFNWRy5kZWZzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBkb3RzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoJChcInN0b3BcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiBkb3RzW2ldLm9mZnNldCA/IGRvdHNbaV0ub2Zmc2V0IDogaSA/IFwiMTAwJVwiIDogXCIwJVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJzdG9wLWNvbG9yXCI6IGRvdHNbaV0uY29sb3IgfHwgXCIjZmZmXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcInN0b3Atb3BhY2l0eVwiOiBpc0Zpbml0ZShkb3RzW2ldLm9wYWNpdHkpID8gZG90c1tpXS5vcGFjaXR5IDogMVxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgICQobywge1xuICAgICAgICAgICAgZmlsbDogZmlsbHVybChpZCksXG4gICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgXCJmaWxsLW9wYWNpdHlcIjogMVxuICAgICAgICB9KTtcbiAgICAgICAgcy5maWxsID0gRTtcbiAgICAgICAgcy5vcGFjaXR5ID0gMTtcbiAgICAgICAgcy5maWxsT3BhY2l0eSA9IDE7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH0sXG4gICAgaXNJRTlvcjEwID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIG1vZGUgPSBkb2N1bWVudC5kb2N1bWVudE1vZGU7XG4gICAgICByZXR1cm4gbW9kZSAmJiAobW9kZSA9PT0gOSB8fCBtb2RlID09PSAxMCk7XG4gICAgfSxcbiAgICBmaWxsdXJsID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICBpZiAoaXNJRTlvcjEwKCkpIHtcbiAgICAgICAgICByZXR1cm4gXCJ1cmwoJyNcIiArIGlkICsgXCInKVwiO1xuICAgICAgfVxuICAgICAgdmFyIGxvY2F0aW9uID0gZG9jdW1lbnQubG9jYXRpb247XG4gICAgICB2Y
57601XIgbG9jYXRpb25TdHJpbmcgPSAoXG4gICAgICAgICAgbG9jYXRpb24ucHJvdG9jb2wgKyAnLy8nICtcbiAgICAgICAgICBsb2NhdGlvbi5ob3N0ICtcbiAgICAgICAgICBsb2NhdGlvbi5wYXRobmFtZSArXG4gICAgICAgICAgbG9jYXRpb24uc2VhcmNoXG4gICAgICApO1xuICAgICAgcmV0dXJuIFwidXJsKCdcIiArIGxvY2F0aW9uU3RyaW5nICsgXCIjXCIgKyBpZCArIFwiJylcIjtcbiAgICB9LFxuICAgIHVwZGF0ZVBvc2l0aW9uID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgdmFyIGJib3ggPSBvLmdldEJCb3goMSk7XG4gICAgICAgICQoby5wYXR0ZXJuLCB7cGF0dGVyblRyYW5zZm9ybTogby5tYXRyaXguaW52ZXJ0KCkgKyBcIiB0cmFuc2xhdGUoXCIgKyBiYm94LnggKyBcIixcIiArIGJib3gueSArIFwiKVwifSk7XG4gICAgfSxcbiAgICBhZGRBcnJvdyA9IGZ1bmN0aW9uIChvLCB2YWx1ZSwgaXNFbmQpIHtcbiAgICAgICAgaWYgKG8udHlwZSA9PSBcInBhdGhcIikge1xuICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFN0cih2YWx1ZSkudG9Mb3dlckNhc2UoKS5zcGxpdChcIi1cIiksXG4gICAgICAgICAgICAgICAgcCA9IG8ucGFwZXIsXG4gICAgICAgICAgICAgICAgc2UgPSBpc0VuZCA/IFwiZW5kXCIgOiBcInN0YXJ0XCIsXG4gICAgICAgICAgICAgICAgbm9kZSA9IG8ubm9kZSxcbiAgICAgICAgICAgICAgICBhdHRycyA9IG8uYXR0cnMsXG4gICAgICAgICAgICAgICAgc3Ryb2tlID0gYXR0cnNbXCJzdHJva2Utd2lkdGhcIl0sXG4gICAgICAgICAgICAgICAgaSA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgdHlwZSA9IFwiY2xhc3NpY1wiLFxuICAgICAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICAgICAgZHgsXG4gICAgICAgICAgICAgICAgcmVmWCxcbiAgICAgICAgICAgICAgICBhdHRyLFxuICAgICAgICAgICAgICAgIHcgPSAzLFxuICAgICAgICAgICAgICAgIGggPSAzLFxuICAgICAgICAgICAgICAgIHQgPSA1O1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodmFsdWVzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJibG9ja1wiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY2xhc3NpY1wiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3ZhbFwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZGlhbW9uZFwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3BlblwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwibm9uZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwid2lkZVwiOiBoID0gNTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJuYXJyb3dcIjogaCA9IDI7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwibG9uZ1wiOiB3ID0gNTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzaG9ydFwiOiB3ID0gMjsgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJvcGVuXCIpIHtcbiAgICAgICAgICAgICAgICB3ICs9IDI7XG4gICAgICAgICAgICAgICAgaCArPSAyO1xuICAgICAgICAgICAgICAgIHQgKz0gMjtcbiAgICAgICAgICAgICAgICBkeCA9IDE7XG4gICAgICAgICAgICAgICAgcmVmWCA9IGlzRW5kID8gNCA6IDE7XG4gICAgICAgICAgICAgICAgYXR0ciA9IHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogXCJub25lXCIsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogYXR0cnMuc3Ryb2tlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVmWCA9IGR4ID0gdyAvIDI7XG4gICAgICAgICAgICAgICAgYXR0ciA9IHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogYXR0cnMuc3Ryb2tlLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2U6IFwibm9uZVwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvLl8uYXJyb3dzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIG8uXy5hcnJvd3MuZW5kUGF0aCAmJiBtYXJrZXJDb3VudGVyW28uXy5hcnJvd3MuZW5kUGF0aF0tLTtcbiAgICAgICAgICAgICAgICAgICAgby5fLmFycm93cy5lbmRNYXJrZXIgJiYgbWFya2VyQ291bnRlcltvLl8uYXJyb3dzLmVuZE1hcmtlcl0tLTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvLl8uYXJyb3dzLnN0YXJ0UGF0aCAmJiBtYXJrZXJDb3VudGVyW28uXy5hcnJvd3Muc3RhcnRQYXRoXS0tO1xuICAgICAgICAgICAgICAgICAgICBvLl8uYXJyb3dzLnN0YXJ0TWFya2VyICYmIG1hcmtlckNvdW50ZXJbby5fLmFycm93cy5zdGFydE1hcmtlcl0tLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG8uXy5hcnJvd3MgPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlICE9IFwibm9uZVwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGhJZCA9IFwicmFwaGFlbC1tYXJrZXItXCIgKyB0eXBlLFxuICAgICAgICAgICAgICAgICAgICBtYXJrZXJJZCA9IFwicmFwaGFlbC1tYXJrZXItXCIgKyBzZSArIHR5cGUgKyB3ICsgaCArIFwiLW9ialwiICsgby5pZDtcbiAgICAgICAgICAgICAgICBpZiAoIVIuX2cuZG9jLmdldEVsZW1lbnRCeUlkKHBhdGhJZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcC5kZWZzLmFwcGVuZENoaWxkKCQoJChcInBhdGhcIiksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwic3Ryb2tlLWxpbmVjYXBcIjogXCJyb3VuZFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgZDogbWFya2Vyc1t0eXBlXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBwYXRoSWRcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXJDb3VudGVyW3BhdGhJZF0gPSAxO1xuICAgICAgICAgICAgICAgI
57601H0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmtlckNvdW50ZXJbcGF0aElkXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbWFya2VyID0gUi5fZy5kb2MuZ2V0RWxlbWVudEJ5SWQobWFya2VySWQpLFxuICAgICAgICAgICAgICAgICAgICB1c2U7XG4gICAgICAgICAgICAgICAgaWYgKCFtYXJrZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgbWFya2VyID0gJCgkKFwibWFya2VyXCIpLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZDogbWFya2VySWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJIZWlnaHQ6IGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJXaWR0aDogdyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudDogXCJhdXRvXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWZYOiByZWZYLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmWTogaCAvIDJcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHVzZSA9ICQoJChcInVzZVwiKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJ4bGluazpocmVmXCI6IFwiI1wiICsgcGF0aElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAoaXNFbmQgPyBcInJvdGF0ZSgxODAgXCIgKyB3IC8gMiArIFwiIFwiICsgaCAvIDIgKyBcIikgXCIgOiBFKSArIFwic2NhbGUoXCIgKyB3IC8gdCArIFwiLFwiICsgaCAvIHQgKyBcIilcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwic3Ryb2tlLXdpZHRoXCI6ICgxIC8gKCh3IC8gdCArIGggLyB0KSAvIDIpKS50b0ZpeGVkKDQpXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXIuYXBwZW5kQ2hpbGQodXNlKTtcbiAgICAgICAgICAgICAgICAgICAgcC5kZWZzLmFwcGVuZENoaWxkKG1hcmtlcik7XG4gICAgICAgICAgICAgICAgICAgIG1hcmtlckNvdW50ZXJbbWFya2VySWRdID0gMTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXJDb3VudGVyW21hcmtlcklkXSsrO1xuICAgICAgICAgICAgICAgICAgICB1c2UgPSBtYXJrZXIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJ1c2VcIilbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICQodXNlLCBhdHRyKTtcbiAgICAgICAgICAgICAgICB2Y
57601XIgZGVsdGEgPSBkeCAqICh0eXBlICE9IFwiZGlhbW9uZFwiICYmIHR5cGUgIT0gXCJvdmFsXCIpO1xuICAgICAgICAgICAgICAgIGlmIChpc0VuZCkge1xuICAgICAgICAgICAgICAgICAgICBmcm9tID0gby5fLmFycm93cy5zdGFydGR4ICogc3Ryb2tlIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgIHRvID0gUi5nZXRUb3RhbExlbmd0aChhdHRycy5wYXRoKSAtIGRlbHRhICogc3Ryb2tlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBkZWx0YSAqIHN0cm9rZTtcbiAgICAgICAgICAgICAgICAgICAgdG8gPSBSLmdldFRvdGFsTGVuZ3RoKGF0dHJzLnBhdGgpIC0gKG8uXy5hcnJvd3MuZW5kZHggKiBzdHJva2UgfHwgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF0dHIgPSB7fTtcbiAgICAgICAgICAgICAgICBhdHRyW1wibWFya2VyLVwiICsgc2VdID0gXCJ1cmwoI1wiICsgbWFya2VySWQgKyBcIilcIjtcbiAgICAgICAgICAgICAgICBpZiAodG8gfHwgZnJvbSkge1xuICAgICAgICAgICAgICAgICAgICBhdHRyLmQgPSBSLmdldFN1YnBhdGgoYXR0cnMucGF0aCwgZnJvbSwgdG8pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkKG5vZGUsIGF0dHIpO1xuICAgICAgICAgICAgICAgIG8uXy5hcnJvd3Nbc2UgKyBcIlBhdGhcIl0gPSBwYXRoSWQ7XG4gICAgICAgICAgICAgICAgby5fLmFycm93c1tzZSArIFwiTWFya2VyXCJdID0gbWFya2VySWQ7XG4gICAgICAgICAgICAgICAgby5fLmFycm93c1tzZSArIFwiZHhcIl0gPSBkZWx0YTtcbiAgICAgICAgICAgICAgICBvLl8uYXJyb3dzW3NlICsgXCJUeXBlXCJdID0gdHlwZTtcbiAgICAgICAgICAgICAgICBvLl8uYXJyb3dzW3NlICsgXCJTdHJpbmdcIl0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBvLl8uYXJyb3dzLnN0YXJ0ZHggKiBzdHJva2UgfHwgMDtcbiAgICAgICAgICAgICAgICAgICAgdG8gPSBSLmdldFRvdGFsTGVuZ3RoKGF0dHJzLnBhdGgpIC0gZnJvbTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmcm9tID0gMDtcbiAgICAgICAgICAgICAgICAgICAgdG8gPSBSLmdldFRvdGFsTGVuZ3RoKGF0dHJzLnBhdGgpIC0gKG8uXy5hcnJvd3MuZW5kZHggKiBzdHJva2UgfHwgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG8uXy5hcnJvd3Nbc2UgKyBcIlBhdGhcIl0gJiYgJChub2RlLCB7ZDogUi5nZXRTdWJwYXRoKGF0dHJzLnBhdGgsIGZyb20sIHRvKX0pO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJQYXRoXCJdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJNYXJrZXJcIl07XG4gICAgICAgICAgICAgICAgZGVsZXRlIG8uXy5hcnJvd3Nbc2UgKyBcImR4XCJdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJUeXBlXCJdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJTdHJpbmdcIl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGF0dHIgaW4gbWFya2VyQ291bnRlcikgaWYgKG1hcmtlckNvdW50ZXJbaGFzXShhdHRyKSAmJiAhbWFya2VyQ291bnRlclthdHRyXSkge1xuICAgICAgICAgICAgICAgIHZhciBpdGVtID0gUi5fZy5kb2MuZ2V0RWxlbWVudEJ5SWQoYXR0cik7XG4gICAgICAgICAgICAgICAgaXRlbSAmJiBpdGVtLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRhc2hhcnJheSA9IHtcbiAgICAgICAgXCItXCI6IFszLCAxXSxcbiAgICAgICAgXCIuXCI6IFsxLCAxXSxcbiAgICAgICAgXCItLlwiOiBbMywgMSwgMSwgMV0sXG4gICAgICAgIFwiLS4uXCI6IFszLCAxLCAxLCAxLCAxLCAxXSxcbiAgICAgICAgXCIuIFwiOiBbMSwgM10sXG4gICAgICAgIFwiLSBcIjogWzQsIDNdLFxuICAgICAgICBcIi0tXCI6IFs4LCAzXSxcbiAgICAgICAgXCItIC5cIjogWzQsI
57601DMsIDEsIDNdLFxuICAgICAgICBcIi0tLlwiOiBbOCwgMywgMSwgM10sXG4gICAgICAgIFwiLS0uLlwiOiBbOCwgMywgMSwgMywgMSwgM11cbiAgICB9LFxuICAgIGFkZERhc2hlcyA9IGZ1bmN0aW9uIChvLCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgICAgIHZhbHVlID0gZGFzaGFycmF5W1N0cih2YWx1ZSkudG9Mb3dlckNhc2UoKV07XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIHdpZHRoID0gby5hdHRyc1tcInN0cm9rZS13aWR0aFwiXSB8fCBcIjFcIixcbiAgICAgICAgICAgICAgICBidXR0ID0ge3JvdW5kOiB3aWR0aCwgc3F1YXJlOiB3aWR0aCwgYnV0dDogMH1bby5hdHRyc1tcInN0cm9rZS1saW5lY2FwXCJdIHx8IHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdXSB8fCAwLFxuICAgICAgICAgICAgICAgIGRhc2hlcyA9IFtdLFxuICAgICAgICAgICAgICAgIGkgPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgZGFzaGVzW2ldID0gdmFsdWVbaV0gKiB3aWR0aCArICgoaSAlIDIpID8gMSA6IC0xKSAqIGJ1dHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkKG8ubm9kZSwge1wic3Ryb2tlLWRhc2hhcnJheVwiOiBkYXNoZXMuam9pbihcIixcIil9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAkKG8ubm9kZSwge1wic3Ryb2tlLWRhc2hhcnJheVwiOiBcIm5vbmVcIn0pO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBzZXRGaWxsQW5kU3Ryb2tlID0gZnVuY3Rpb24gKG8sIHBhcmFtcykge1xuICAgICAgICB2Y
57601XIgbm9kZSA9IG8ubm9kZSxcbiAgICAgICAgICAgIGF0dHJzID0gby5hdHRycyxcbiAgICAgICAgICAgIHZpcyA9IG5vZGUuc3R5bGUudmlzaWJpbGl0eTtcbiAgICAgICAgbm9kZS5zdHlsZS52aXNpYmlsaXR5ID0gXCJoaWRkZW5cIjtcbiAgICAgICAgZm9yICh2YXIgYXR0IGluIHBhcmFtcykge1xuICAgICAgICAgICAgaWYgKHBhcmFtc1toYXNdKGF0dCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIVIuX2F2YWlsYWJsZUF0dHJzW2hhc10oYXR0KSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcGFyYW1zW2F0dF07XG4gICAgICAgICAgICAgICAgYXR0cnNbYXR0XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoYXR0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJibHVyXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBvLmJsdXIodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0aXRsZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRpdGxlID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZShcInRpdGxlXCIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIGV4aXN0aW5nIDx0aXRsZT4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGl0bGUubGVuZ3RoICYmICh0aXRsZSA9IHRpdGxlWzBdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS5maXJzdENoaWxkLm5vZGVWYWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAkKFwidGl0bGVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWwgPSBSLl9nLmRvYy5jcmVhdGVUZXh0Tm9kZSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmFwcGVuZENoaWxkKHZhbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGl0bGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJocmVmXCI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0YXJnZXRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwbiA9IG5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwbi50YWdOYW1lLnRvTG93ZXJDYXNlKCkgIT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgaGwgPSAkKFwiYVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbi5pbnNlcnRCZWZvcmUoaGwsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhsLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBuID0gaGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ID09IFwidGFyZ2V0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbi5zZXRBdHRyaWJ1dGVOUyh4bGluaywgXCJzaG93XCIsIHZhbHVlID09IFwiYmxhbmtcIiA/IFwibmV3XCIgOiB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBuLnNldEF0dHJpYnV0ZU5TKHhsaW5rLCBhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3Vyc29yXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlLmN1cnNvciA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0cmFuc2Zvcm1cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG8udHJhbnNmb3JtKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYXJyb3ctc3RhcnRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZEFycm93KG8sIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYXJyb3ctZW5kXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRBcnJvdyhvLCB2YWx1ZSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNsaXAtcmVjdFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlY3QgPSBTdHIodmFsdWUpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVjdC5sZW5ndGggPT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG8uY2xpcCAmJiBvLmNsaXAucGFyZW50Tm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG8uY2xpcC5wYXJlbnROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgZWwgPSAkKFwiY2xpcFBhdGhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJjID0gJChcInJlY3RcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaWQgPSBSLmNyZWF0ZVVVSUQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHJjLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg6IHJlY3RbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk6IHJlY3RbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiByZWN0WzJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHJlY3RbM11cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5hcHBlbmRDaGlsZChyYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgby5wYXBlci5kZWZzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtcImNsaXAtcGF0aFwiOiBcInVybCgjXCIgKyBlbC5pZCArIFwiKVwifSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgby5jbGlwID0gcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBhdGggPSBub2RlLmdldEF0dHJpYnV0ZShcImNsaXAtcGF0aFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGF0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgY2xpcCA9IFIuX2cuZG9jLmdldEVsZW1lbnRCeUlkKHBhdGgucmVwbGFjZSgvKF51cmxcXCgjfFxcKSQpL2csIEUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcCAmJiBjbGlwLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY2xpcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge1wiY2xpcC1wYXRoXCI6IEV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG8uY2xpcDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8udHlwZSA9PSBcInBhdGhcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge2Q6IHZhbHVlID8gYXR0cnMucGF0aCA9IFIuX3BhdGhUb0Fic29sdXRlKHZhbHVlKSA6IFwiTTAsMFwifSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoby5fLmFycm93cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0YXJ0U3RyaW5nXCIgaW4gby5fLmFycm93cyAmJiBhZGRBcnJvdyhvLCBvLl8uYXJyb3dzLnN0YXJ0U3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJlbmRTdHJpbmdcIiBpbiBvLl8uYXJyb3dzICYmIGFkZEFycm93KG8sIG8uXy5hcnJvd3MuZW5kU3RyaW5nLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIndpZHRoXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG8uXy5kaXJ0eSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0cnMuZngpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHQgPSBcInhcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGF0dHJzLng7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwieFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmZ4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSAtYXR0cnMueCAtIChhdHRycy53aWR0aCB8fCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInJ4XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ID09IFwicnhcIiAmJiBvLnR5cGUgPT0gXCJyZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImN4XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG8ucGF0dGVybiAmJiB1cGRhdGVQb3NpdGlvbihvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG8uXy5kaXJ0eSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImhlaWdodFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvLl8uZGlydHkgPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmZ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0ID0gXCJ5XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBhdHRycy55O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInlcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRycy5meSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gLWF0dHJzLnkgLSAoYXR0cnMuaGVpZ2h0IHx8IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicnlcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHQgPT0gXCJyeVwiICYmIG8udHlwZSA9PSBcInJlY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3lcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgby5wYXR0ZXJuICYmIHVwZGF0ZVBvc2l0aW9uKG8pO1xuICAgICAgICAgICAgICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiclwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8udHlwZSA9PSBcInJlY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge3J4OiB2YWx1ZSwgcnk6IHZhbHVlfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwic3JjXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoby50eXBlID09IFwiaW1hZ2VcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlTlMoeGxpbmssIFwiaHJlZlwiLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInN0cm9rZS13aWR0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8uXy5zeCAhPSAxIHx8IG8uXy
576015zeSAhPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgLz0gbW1heChhYnMoby5fLnN4KSwgYWJzKG8uXy5zeSkpIHx8IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyc1tcInN0cm9rZS1kYXNoYXJyYXlcIl0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGREYXNoZXMobywgYXR0cnNbXCJzdHJva2UtZGFzaGFycmF5XCJdLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8uXy5hcnJvd3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0YXJ0U3RyaW5nXCIgaW4gby5fLmFycm93cyAmJiBhZGRBcnJvdyhvLCBvLl8uYXJyb3dzLnN0YXJ0U3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImVuZFN0cmluZ1wiIGluIG8uXy5hcnJvd3MgJiYgYWRkQXJyb3cobywgby5fLmFycm93cy5lbmRTdHJpbmcsIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzdHJva2UtZGFzaGFycmF5XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGREYXNoZXMobywgdmFsdWUsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImZpbGxcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1VSTCA9IFN0cih2YWx1ZSkubWF0Y2goUi5fSVNVUkwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVVJMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwgPSAkKFwicGF0dGVyblwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgaWcgPSAkKFwiaW1hZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaWQgPSBSLmNyZWF0ZVVVSUQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKGVsLCB7eDogMCwgeTogMCwgcGF0dGVyblVuaXRzOiBcInVzZXJTcGFjZU9uVXNlXCIsIGhlaWdodDogMSwgd2lkdGg6IDF9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKGlnLCB7eDogMCwgeTogMCwgXCJ4bGluazpocmVmXCI6IGlzVVJMWzFdfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoaWcpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSLl9wcmVsb2FkKGlzVVJMWzFdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdyA9IHRoaXMub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaCA9IHRoaXMub2Zmc2V0SGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChlbCwge3dpZHRoOiB3LCBoZWlnaHQ6IGh9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoaWcsIHt3aWR0aDogdywgaGVpZ2h0OiBofSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhcGVyLmRlZnMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge2ZpbGw6IFwidXJsKCNcIiArIGVsLmlkICsgXCIpXCJ9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhdHRlcm4gPSBlbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhdHRlcm4gJiYgdXBkYXRlUG9zaXRpb24obyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgY2xyID0gUi5nZXRSR0IodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjbHIuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgcGFyYW1zLmdyYWRpZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBhdHRycy5ncmFkaWVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAhUi5pcyhhdHRycy5vcGFjaXR5LCBcInVuZGVmaW5lZFwiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSLmlzKHBhcmFtcy5vcGFjaXR5LCBcInVuZGVmaW5lZFwiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtvcGFjaXR5OiBhdHRycy5vcGFjaXR5fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIVIuaXMoYXR0cnNbXCJmaWxsLW9wYWNpdHlcIl0sIFwidW5kZWZpbmVkXCIpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFIuaXMocGFyYW1zW1wiZmlsbC1vcGFjaXR5XCJdLCBcInVuZGVmaW5lZFwiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtcImZpbGwtb3BhY2l0eVwiOiBhdHRyc1tcImZpbGwtb3BhY2l0eVwiXX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoby50eXBlID09IFwiY2lyY2xlXCIgfHwgby50eXBlID09IFwiZWxsaXBzZVwiIHx8IFN0cih2YWx1ZSkuY2hhckF0KCkgIT0gXCJyXCIpICYmIGFkZEdyYWRpZW50RmlsbChvLCB2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJvcGFjaXR5XCIgaW4gYXR0cnMgfHwgXCJmaWxsLW9wYWNpdHlcIiBpbiBhdHRycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgZ3JhZGllbnQgPSBSLl9nLmRvYy5nZXRFbGVtZW50QnlJZChub2RlLmdldEF0dHJpYnV0ZShcImZpbGxcIikucmVwbGFjZSgvXnVybFxcKCN8XFwpJC9nLCBFKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChncmFkaWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0b3BzID0gZ3JhZGllbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdG9wXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChzdG9wc1tzdG9wcy5sZW5ndGggLSAxXSwge1wic3RvcC1vcGFjaXR5XCI6IChcIm9wYWNpdHlcIiBpbiBhdHRycyA/IGF0dHJzLm9wYWNpdHkgOiAxKSAqIChcImZpbGwtb3BhY2l0eVwiIGluIGF0dHJzID8gYXR0cnNbXCJmaWxsLW9wYWNpdHlcIl0gOiAxKX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJzLmdyYWRpZW50ID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0cnMuZmlsbCA9IFwibm9uZVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xyW2hhc10oXCJvcGFjaXR5XCIpICYmICQobm9kZSwge1wiZmlsbC1vcGFjaXR5XCI6IGNsci5vcGFjaXR5ID4gMSA/IGNsci5vcGFjaXR5IC8gMTAwIDogY2xyLm9wYWNpdHl9KTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInN0cm9rZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xyID0gUi5nZXRSR0IodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0LCBjbHIuaGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dCA9PSBcInN0cm9rZVwiICYmIGNscltoYXNdKFwib3BhY2l0eVwiKSAmJiAkKG5vZGUsIHtcInN0cm9rZS1vcGFjaXR5XCI6IGNsci5vcGFjaXR5ID4gMSA/IGNsci5vcGFjaXR5IC8gMTAwIDogY2xyLm9wYWNpdHl9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHQgPT0gXCJzdHJva2VcIiAmJiBvLl8uYXJyb3dzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJzdGFydFN0cmluZ1wiIGluIG8uXy5hcnJvd3MgJiYgYWRkQXJyb3cobywgby5fLmFycm93cy5zdGFydFN0cmluZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJlbmRTdHJpbmdcIiBpbiBvLl8uYXJyb3dzICYmIGFkZEFycm93KG8sIG8uXy5hcnJvd3MuZW5kU3RyaW5nLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZ3JhZGllbnRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIChvLnR5cGUgPT0gXCJjaXJjbGVcIiB8fCBvLnR5cGUgPT0gXCJlbGxpcHNlXCIgfHwgU3RyKHZhbHVlKS5jaGFyQXQoKSAhPSBcInJcIikgJiYgYWRkR3JhZGllbnRGaWxsKG8sIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3BhY2l0eVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmdyYWRpZW50ICYmICFhdHRyc1toYXNdKFwic3Ryb2tlLW9wYWNpdHlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtcInN0cm9rZS1vcGFjaXR5XCI6IHZhbHVlID4gMSA/IHZhbHVlIC8gMTAwIDogdmFsdWV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhbGxcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImZpbGwtb3BhY2l0eVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQgPSBSLl9nLmRvYy5nZXRFbGVtZW50QnlJZChub2RlLmdldEF0dHJpYnV0ZShcImZpbGxcIikucmVwbGFjZSgvXnVybFxcKCN8XFwpJC9nLCBFKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3BzID0gZ3JhZGllbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdG9wXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHN0b3BzW3N0b3BzLmxlbmd0aCAtIDFdLCB7XCJzdG9wLW9wYWNpdHlcIjogdmFsdWV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBhdHQgPT0gXCJmb250LXNpemVcIiAmJiAodmFsdWUgPSB0b0ludCh2YWx1ZSwgMTApICsgXCJweFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjc3NydWxlID0gYXR0LnJlcGxhY2UoLyhcXC0uKS9nLCBmdW5jdGlvbiAodykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3LnN1YnN0cmluZygxKS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2Nzc3J1bGVdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBvLl8uZGlydHkgPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0dW5lVGV4dChvLCBwYXJhbXMpO1xuICAgICAgICBub2RlLnN0eWxlLnZpc2liaWxpdHkgPSB2aXM7XG4gICAgfSxcbiAgICBsZWFkaW5nID0gMS4yLFxuICAgIHR1bmVUZXh0ID0gZnVuY3Rpb24gKGVsLCBwYXJhbXMpIHtcbiAgICAgICAgaWYgKGVsLnR5cGUgIT0gXCJ0ZXh0XCIgfHwgIShwYXJhbXNbaGFzXShcInRleHRcIikgfHwgcGFyYW1zW2hhc10oXCJmb250XCIpIHx8IHBhcmFtc1toYXNdKFwiZm9udC1zaXplXCIpIHx8IHBhcmFtc1toYXNdKFwieFwiKSB8fCBwYXJhbXNbaGFzXShcInlcIikpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgI
57601H1cbiAgICAgICAgdmFyIGEgPSBlbC5hdHRycyxcbiAgICAgICAgICAgIG5vZGUgPSBlbC5ub2RlLFxuICAgICAgICAgICAgZm9udFNpemUgPSBub2RlLmZpcnN0Q2hpbGQgPyB0b0ludChSLl9nLmRvYy5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKG5vZGUuZmlyc3RDaGlsZCwgRSkuZ2V0UHJvcGVydHlWYWx1ZShcImZvbnQtc2l6ZVwiKSwgMTApIDogMTA7XG5cbiAgICAgICAgaWYgKHBhcmFtc1toYXNdKFwidGV4dFwiKSkge1xuICAgICAgICAgICAgYS50ZXh0ID0gcGFyYW1zLnRleHQ7XG4gICAgICAgICAgICB3aGlsZSAobm9kZS5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVDaGlsZChub2RlLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHRleHRzID0gU3RyKHBhcmFtcy50ZXh0KS5zcGxpdChcIlxcblwiKSxcbiAgICAgICAgICAgICAgICB0c3BhbnMgPSBbXSxcbiAgICAgICAgICAgICAgICB0c3BhbjtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHRleHRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0c3BhbiA9ICQoXCJ0c3BhblwiKTtcbiAgICAgICAgICAgICAgICBpICYmICQodHNwYW4sIHtkeTogZm9udFNpemUgKiBsZWFkaW5nLCB4OiBhLnh9KTtcbiAgICAgICAgICAgICAgICB0c3Bhbi5hcHBlbmRDaGlsZChSLl9nLmRvYy5jcmVhdGVUZXh0Tm9kZSh0ZXh0c1tpXSkpO1xuICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodHNwYW4pO1xuICAgICAgICAgICAgICAgIHRzcGFuc1tpXSA9IHRzcGFuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHNwYW5zID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZShcInRzcGFuXCIpO1xuICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSB0c3BhbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgaWYgKGkpIHtcbiAgICAgICAgICAgICAgICAkKHRzcGFuc1tpXSwge2R5OiBmb250U2l6ZSAqIGxlYWRpbmcsIHg6IGEueH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKHRzcGFuc1swXSwge2R5OiAwfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgJChub2RlLCB7eDogYS54LCB5OiBhLnl9KTtcbiAgICAgICAgZWwuXy5kaXJ0eSA9IDE7XG4gICAgICAgIHZhciBiYiA9IGVsLl9nZXRCQm94KCksXG4gICAgICAgICAgICBkaWYgPSBhLnkgLSAoYmIueSArIGJiLmhlaWdodCAvIDIpO1xuICAgICAgICBkaWYgJiYgUi5pcyhkaWYsIFwiZmluaXRlXCIpICYmICQodHNwYW5zWzBdLCB7ZHk6IGRpZn0pO1xuICAgIH0sXG4gICAgZ2V0UmVhbE5vZGUgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBpZiAobm9kZS5wYXJlbnROb2RlICYmIG5vZGUucGFyZW50Tm9kZS50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiYVwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9kZS5wYXJlbnROb2RlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIEVsZW1lbnQgPSBmdW5jdGlvbiAobm9kZSwgc3ZnKSB7XG4gICAgICAgIHZhciBYID0gMCxcbiAgICAgICAgICAgIFkgPSAwO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQubm9kZVxuICAgICAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBHaXZlcyB5b3UgYSByZWZlcmVuY2UgdG8gdGhlIERPTSBvYmplY3QsIHNvIHlvdSBjYW4gYXNzaWduIGV2ZW50IGhhbmRsZXJzIG9yIGp1c3QgbWVzcyBhcm91bmQuXG4gICAgICAgICAqKlxuICAgICAgICAgKiBOb3RlOiBEb27igJl0IG1lc3Mgd2l0aCBpdC5cbiAgICAgICAgID4gVXNhZ2VcbiAgICAgICAgIHwgLy8gZHJhdyBhIGNpcmNsZSBhdCBjb29yZGluYXRlIDEwLDEwIHdpdGggcmFkaXVzIG9mIDEwXG4gICAgICAgICB8IHZhciBjID0gcGFwZXIuY2lyY2xlKDEwLCAxMCwgMTApO1xuICAgICAgICAgfCBjLm5vZGUub25jbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgIHwgICAgIGMuYXR0cihcImZpbGxcIiwgXCJyZWRcIik7XG4gICAgICAgICB8IH07XG4gICAgICAgIFxcKi9cbiAgICAgICAgdGhpc1swXSA9IHRoaXMubm9kZSA9IG5vZGU7XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogRWxlbWVudC5yYXBoYWVsXG4gICAgICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIEludGVybmFsIHJlZmVyZW5jZSB0byBAUmFwaGFlbCBvYmplY3QuIEluIGNhc2UgaXQgaXMgbm90IGF2YWlsYWJsZS5cbiAgICAgICAgID4gVXNhZ2VcbiAgICAgICAgIHwgUmFwaGFlbC5lbC5yZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICB8ICAgICB2YXIgaHNiID0gdGhpcy5wYXBlci
576015yYXBoYWVsLnJnYjJoc2IodGhpcy5hdHRyKFwiZmlsbFwiKSk7XG4gICAgICAgICB8ICAgICBoc2IuaCA9IDE7XG4gICAgICAgICB8ICAgICB0aGlzLmF0dHIoe2ZpbGw6IHRoaXMucGFwZXIucmFwaGFlbC5oc2IycmdiKGhzYikuaGV4fSk7XG4gICAgICAgICB8IH1cbiAgICAgICAgXFwqL1xuICAgICAgICBub2RlLnJhcGhhZWwgPSB0cnVlO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQuaWRcbiAgICAgICAgIFsgcHJvcGVydHkgKG51bWJlcikgXVxuICAgICAgICAgKipcbiAgICAgICAgICogVW5pcXVlIGlkIG9mIHRoZSBlbGVtZW50LiBFc3BlY2lhbGx5IHVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvIGxpc3RlbiB0byBldmVudHMgb2YgdGhlIGVsZW1lbnQsXG4gICAgICAgICAqIGJlY2F1c2UgYWxsIGV2ZW50cyBhcmUgZmlyZWQgaW4gZm9ybWF0IGA8bW9kdWxlPi48YWN0aW9uPi48aWQ+YC4gQWxzbyB1c2VmdWwgZm9yIEBQYXBlci5nZXRCeUlkIG1ldGhvZC5cbiAgICAgICAgXFwqL1xuICAgICAgICB0aGlzLmlkID0gZ3VpZCgpO1xuICAgICAgICBub2RlLnJhcGhhZWxpZCA9IHRoaXMuaWQ7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICogTWV0aG9kIHRoYXQgcmV0dXJucyBhIDUgbGV0dGVyL2RpZ2l0IGlkLCBlbm91Z2ggZm9yIDM2XjUgPSA2MDQ2NjE3NiBlbGVtZW50c1xuICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IGlkXG4gICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGd1aWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gKFwiMDAwMFwiICsgKE1hdGgucmFuZG9tKCkqTWF0aC5wb3coMzYsNSkgPDwgMCkudG9TdHJpbmcoMzYpKS5zbGljZSgtNSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1hdHJpeCA9IFIubWF0cml4KCk7XG4gICAgICAgIHRoaXMucmVhbFBhdGggPSBudWxsO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQucGFwZXJcbiAgICAgICAgIFsgcHJvcGVydHkgKG9iamVjdCkgXVxuICAgICAgICAgKipcbiAgICAgICAgICogSW50ZXJuYWwgcmVmZXJlbmNlIHRvIOKAnHBhcGVy4oCdIHdoZXJlIG9iamVjdCBkcmF3bi4gTWFpbmx5IGZvciB1c2UgaW4gcGx1Z2lucyBhbmQgZWxlbWVudCBleHRlbnNpb25zLlxuICAgICAgICAgPiBVc2FnZVxuICAgICAgICAgfCBSYXBoYWVsLmVsLmNyb3NzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgfCAgICAgdGhpcy5hdHRyKHtmaWxsOiBcInJlZFwifSk7XG4gICAgICAgICB8ICAgICB0aGlzLnBhcGVyLnBhdGgoXCJNMTAsMTBMNTAsNTBNNTAsMTBMMTAsNTBcIilcbiAgICAgICAgIHwgICAgICAgICAuYXR0cih7c3Ryb2tlOiBcInJlZFwifSk7XG4gICAgICAgICB8IH1cbiAgICAgICAgXFwqL1xuICAgICAgICB0aGlzLnBhcGVyID0gc3ZnO1xuICAgICAgICB0aGlzLmF0dHJzID0gdGhpcy5hdHRycyB8fCB7fTtcbiAgICAgICAgdGhpcy5fID0ge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBbXSxcbiAgICAgICAgICAgIHN4OiAxLFxuICAgICAgICAgICAgc3k6IDEsXG4gICAgICAgICAgICBkZWc6IDAsXG4gICAgICAgICAgICBkeDogMCxcbiAgICAgICAgICAgIGR5OiAwLFxuICAgICAgICAgICAgZGlydHk6IDFcbiAgICAgICAgfTtcbiAgICAgICAgIXN2Zy5ib3R0b20gJiYgKHN2Zy5ib3R0b20gPSB0aGlzKTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBFbGVtZW50LnByZXZcbiAgICAgICAgIFsgcHJvcGVydHkgKG9iamVjdCkgXVxuICAgICAgICAgKipcbiAgICAgICAgICogUmVmZXJlbmNlIHRvIHRoZSBwcmV2aW91cyBlbGVtZW50IGluIHRoZSBoaWVyYXJjaHkuXG4gICAgICAgIFxcKi9cbiAgICAgICAgdGhpcy5wcmV2ID0gc3ZnLnRvcDtcbiAgICAgICAgc3ZnLnRvcCAmJiAoc3ZnLnRvcC5uZXh0ID0gdGhpcyk7XG4gICAgICAgIHN2Zy50b3AgPSB0aGlzO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQubmV4dFxuICAgICAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSZWZlcmVuY2UgdG8gdGhlIG5leHQgZWxlbWVudCBpbiB0aGUgaGllcmFyY2h5LlxuICAgICAgICBcXCovXG4gICAgICAgIHRoaXMubmV4dCA9IG51bGw7XG4gICAgfSxcbiAgICBlbHByb3RvID0gUi5lbDtcblxuICAgIEVsZW1lbnQucHJvdG90eXBlID0gZWxwcm90bztcbiAgICBlbHByb3RvLmNvbnN0cnVjdG9yID0gRWxlbWVudDtcblxuICAgIFIuX2VuZ2luZS5wYXRoID0gZnVuY3Rpb24gKHBhdGhTdHJpbmcsIFNWRykge1xuICAgICAgICB2Y
57601XIgZWwgPSAkKFwicGF0aFwiKTtcbiAgICAgICAgU1ZHLmNhbnZhcyAmJiBTVkcuY2FudmFzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgdmFyIHAgPSBuZXcgRWxlbWVudChlbCwgU1ZHKTtcbiAgICAgICAgcC50eXBlID0gXCJwYXRoXCI7XG4gICAgICAgIHNldEZpbGxBbmRTdHJva2UocCwge1xuICAgICAgICAgICAgZmlsbDogXCJub25lXCIsXG4gICAgICAgICAgICBzdHJva2U6IFwiIzAwMFwiLFxuICAgICAgICAgICAgcGF0aDogcGF0aFN0cmluZ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5yb3RhdGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERlcHJlY2F0ZWQhIFVzZSBARWxlbWVudC50cmFuc2Zvcm0gaW5zdGVhZC5cbiAgICAgKiBBZGRzIHJvdGF0aW9uIGJ5IGdpdmVuIGFuZ2xlIGFyb3VuZCBnaXZlbiBwb2ludCB0byB0aGUgbGlzdCBvZlxuICAgICAqIHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gZGVnIChudW1iZXIpIGFuZ2xlIGluIGRlZ3JlZXNcbiAgICAgLSBjeCAobnVtYmVyKSAjb3B0aW9uYWwgeCBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygcm90YXRpb25cbiAgICAgLSBjeSAobnVtYmVyKSAjb3B0aW9uYWwgeSBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygcm90YXRpb25cbiAgICAgKiBJZiBjeCAmIGN5IGFyZW7igJl0IHNwZWNpZmllZCBjZW50cmUgb2YgdGhlIHNoYXBlIGlzIHVzZWQgYXMgYSBwb2ludCBvZiByb3RhdGlvbi5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnJvdGF0ZSA9IGZ1bmN0aW9uIChkZWcsIGN4LCBjeSkge1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBkZWcgPSBTdHIoZGVnKS5zcGxpdChzZXBhcmF0b3IpO1xuICAgICAgICBpZiAoZGVnLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIGN4ID0gdG9GbG9hdChkZWdbMV0pO1xuICAgICAgICAgICAgY3kgPSB0b0Zsb2F0KGRlZ1syXSk7XG4gICAgICAgIH1cbiAgICAgICAgZGVnID0gdG9GbG9hdChkZWdbMF0pO1xuICAgICAgICAoY3kgPT0gbnVsbCkgJiYgKGN4ID0gY3kpO1xuICAgICAgICBpZiAoY3ggPT0gbnVsbCB8fCBjeSA9PSBudWxsKSB7XG4gICAgICAgICAgICB2Y
57601XIgYmJveCA9IHRoaXMuZ2V0QkJveCgxKTtcbiAgICAgICAgICAgIGN4ID0gYmJveC54ICsgYmJveC53aWR0aCAvIDI7XG4gICAgICAgICAgICBjeSA9IGJib3gueSArIGJib3guaGVpZ2h0IC8gMjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyYW5zZm9ybSh0aGlzLl8udHJhbnNmb3JtLmNvbmNhdChbW1wiclwiLCBkZWcsIGN4LCBjeV1dKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuc2NhbGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERlcHJlY2F0ZWQhIFVzZSBARWxlbWVudC50cmFuc2Zvcm0gaW5zdGVhZC5cbiAgICAgKiBBZGRzIHNjYWxlIGJ5IGdpdmVuIGFtb3VudCByZWxhdGl2ZSB0byBnaXZlbiBwb2ludCB0byB0aGUgbGlzdCBvZlxuICAgICAqIHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gc3ggKG51bWJlcikgaG9yaXNvbnRhbCBzY2FsZSBhbW91bnRcbiAgICAgLSBzeSAobnVtYmVyKSB2ZXJ0aWNhbCBzY2FsZSBhbW91bnRcbiAgICAgLSBjeCAobnVtYmVyKSAjb3B0aW9uYWwgeCBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygc2NhbGVcbiAgICAgLSBjeSAobnVtYmVyKSAjb3B0aW9uYWwgeSBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygc2NhbGVcbiAgICAgKiBJZiBjeCAmIGN5IGFyZW7igJl0IHNwZWNpZmllZCBjZW50cmUgb2YgdGhlIHNoYXBlIGlzIHVzZWQgaW5zdGVhZC5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnNjYWxlID0gZnVuY3Rpb24gKHN4LCBzeSwgY3gsIGN5KSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHN4ID0gU3RyKHN4KS5zcGxpdChzZXBhcmF0b3IpO1xuICAgICAgICBpZiAoc3gubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgc3kgPSB0b0Zsb2F0KHN4WzFdKTtcbiAgICAgICAgICAgIGN4ID0gdG9GbG9hdChzeFsyXSk7XG4gICAgICAgICAgICBjeSA9IHRvRmxvYXQoc3hbM10pO1xuICAgICAgICB9XG4gICAgICAgIHN4ID0gdG9GbG9hdChzeFswXSk7XG4gICAgICAgIChzeSA9PSBudWxsKSAmJiAoc3kgPSBzeCk7XG4gICAgICAgIChjeSA9PSBudWxsKSAmJiAoY3ggPSBjeSk7XG4gICAgICAgIGlmIChjeCA9PSBudWxsIHx8IGN5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBiYm94ID0gdGhpcy5nZXRCQm94KDEpO1xuICAgICAgICB9XG4gICAgICAgIGN4ID0gY3ggPT0gbnVsbCA/IGJib3gueCArIGJib3gud2lkdGggLyAyIDogY3g7XG4gICAgICAgIGN5ID0gY3kgPT0gbnVsbCA/IGJib3gueSArIGJib3guaGVpZ2h0IC8gMiA6IGN5O1xuICAgICAgICB0aGlzLnRyYW5zZm9ybSh0aGlzLl8udHJhbnNmb3JtLmNvbmNhdChbW1wic1wiLCBzeCwgc3ksIGN4LCBjeV1dKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudHJhbnNsYXRlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBEZXByZWNhdGVkISBVc2UgQEVsZW1lbnQudHJhbnNmb3JtIGluc3RlYWQuXG4gICAgICogQWRkcyB0cmFuc2xhdGlvbiBieSBnaXZlbiBhbW91bnQgdG8gdGhlIGxpc3Qgb2YgdHJhbnNmb3JtYXRpb25zIG9mIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBkeCAobnVtYmVyKSBob3Jpc29udGFsIHNoaWZ0XG4gICAgIC0gZHkgKG51bWJlcikgdmVydGljYWwgc2hpZnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChkeCwgZHkpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZHggPSBTdHIoZHgpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChkeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBkeSA9IHRvRmxvYXQoZHhbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGR4ID0gdG9GbG9hdChkeFswXSkgfHwgMDtcbiAgICAgICAgZHkgPSArZHkgfHwgMDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0odGhpcy5fLnRyYW5zZm9ybS5jb25jYXQoW1tcInRcIiwgZHgsIGR5XV0pKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC50cmFuc2Zvcm1cbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgdHJhbnNmb3JtYXRpb24gdG8gdGhlIGVsZW1lbnQgd2hpY2ggaXMgc2VwYXJhdGUgdG8gb3RoZXIgYXR0cmlidXRlcyxcbiAgICAgKiBpLmUuIHRyYW5zbGF0aW9uIGRvZXNu4oCZdCBjaGFuZ2UgYHhgIG9yIGB5YCBvZiB0aGUgcmVjdGFuZ2UuIFRoZSBmb3JtYXRcbiAgICAgKiBvZiB0cmFuc2Zvcm1hdGlvbiBzdHJpbmcgaXMgc2ltaWxhciB0byB0aGUgcGF0aCBzdHJpbmcgc3ludGF4OlxuICAgICB8IFwidDEwMCwxMDByMzAsMTAwLDEwMHMyLDIsMTAwLDEwMHI0NXMxLjVcIlxuICAgICAqIEVhY2ggbGV0dGVyIGlzIGEgY29tbWFuZC4gVGhlcmUgYXJlIGZvdXIgY29tbWFuZHM6IGB0YCBpcyBmb3IgdHJhbnNsYXRlLCBgcmAgaXMgZm9yIHJvdGF0ZSwgYHNgIGlzIGZvclxuICAgICAqIHNjYWxlIGFuZCBgbWAgaXMgZm9yIG1hdHJpeC5cbiAgICAgKlxuICAgICAqIFRoZXJlIGFyZSBhbHNvIGFsdGVybmF0aXZlIOKAnGFic29sdXRl4oCdIHRyYW5zbGF0aW9uLCByb3RhdGlvbiBhbmQgc2NhbGU6IGBUYCwgYFJgIGFuZCBgU2AuIFRoZXkgd2lsbCBub3QgdGFrZSBwcmV2aW91cyB0cmFuc2Zvcm1hdGlvbiBpbnRvIGFjY291bnQuIEZvciBleGFtcGxlLCBgLi4uVDEwMCwwYCB3aWxsIGFsd2F5cyBtb3ZlIGVsZW1lbnQgMTAwIHB4IGhvcmlzb250YWxseSwgd2hpbGUgYC4uLnQxMDAsMGAgY291bGQgbW92ZSBpdCB2ZXJ0aWNhbGx5IGlmIHRoZXJlIGlzIGByOTBgIGJlZm9yZS4gSnVzdCBjb21wYXJlIHJlc3VsdHMgb2YgYHI5MHQxMDAsMGAgYW5kIGByOTBUMTAwLDBgLlxuICAgICAqXG4gICAgICogU28sIHRoZSBleGFtcGxlIGxpbmUgYWJvdmUgY291bGQgYmUgcmVhZCBsaWtlIOKAnHRyYW5zbGF0ZSBieSAxMDAsIDEwMDsgcm90YXRlIDMwwrAgYXJvdW5kIDEwMCwgMTAwOyBzY2FsZSB0d2ljZSBhcm91bmQgMTAwLCAxMDA7XG4gICAgICogcm90YXRlIDQ1wrAgYXJvdW5kIGNlbnRyZTsgc2NhbGUgMS41IHRpbWVzIHJlbGF0aXZlIHRvIGNlbnRyZeKAnS4gQXMgeW91IGNhbiBzZWUgcm90YXRlIGFuZCBzY2FsZSBjb21tYW5kcyBoYXZlIG9yaWdpblxuICAgICAqIGNvb3JkaW5hdGVzIGFzIG9wdGlvbmFsIHBhcmFtZXRlcnMsIHRoZSBkZWZhdWx0IGlzIHRoZSBjZW50cmUgcG9pbnQgb2YgdGhlIGVsZW1lbnQuXG4gICAgICogTWF0cml4IGFjY2VwdHMgc2l4IHBhcmFtZXRlcnMuXG4gICAgID4gVXNhZ2
57601VcbiAgICAgfCB2YXIgZWwgPSBwYXBlci5yZWN0KDEwLCAyMCwgMzAwLCAyMDApO1xuICAgICB8IC8vIHRyYW5zbGF0ZSAxMDAsIDEwMCwgcm90YXRlIDQ1wrAsIHRyYW5zbGF0ZSAtMTAwLCAwXG4gICAgIHwgZWwudHJhbnNmb3JtKFwidDEwMCwxMDByNDV0LTEwMCwwXCIpO1xuICAgICB8IC8vIGlmIHlvdSB3YW50IHlvdSBjYW4gYXBwZW5kIG9yIHByZXBlbmQgdHJhbnNmb3JtYXRpb25zXG4gICAgIHwgZWwudHJhbnNmb3JtKFwiLi4udDUwLDUwXCIpO1xuICAgICB8IGVsLnRyYW5zZm9ybShcInMyLi4uXCIpO1xuICAgICB8IC8vIG9yIGV2ZW4gd3JhcFxuICAgICB8IGVsLnRyYW5zZm9ybShcInQ1MCw1MC4uLnQtNTAtNTBcIik7XG4gICAgIHwgLy8gdG8gcmVzZXQgdHJhbnNmb3JtYXRpb24gY2FsbCBtZXRob2Qgd2l0aCBlbXB0eSBzdHJpbmdcbiAgICAgfCBlbC50cmFuc2Zvcm0oXCJcIik7XG4gICAgIHwgLy8gdG8gZ2V0IGN1cnJlbnQgdmFsdWUgY2FsbCBpdCB3aXRob3V0IHBhcmFtZXRlcnNcbiAgICAgfCBjb25zb2xlLmxvZyhlbC50cmFuc2Zvcm0oKSk7XG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHRzdHIgKHN0cmluZykgI29wdGlvbmFsIHRyYW5zZm9ybWF0aW9uIHN0cmluZ1xuICAgICAqIElmIHRzdHIgaXNu4oCZdCBzcGVjaWZpZWRcbiAgICAgPSAoc3RyaW5nKSBjdXJyZW50IHRyYW5zZm9ybWF0aW9uIHN0cmluZ1xuICAgICAqIGVsc2VcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0c3RyKSB7XG4gICAgICAgIHZhciBfID0gdGhpcy5fO1xuICAgICAgICBpZiAodHN0ciA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gXy50cmFuc2Zvcm07XG4gICAgICAgIH1cbiAgICAgICAgUi5fZXh0cmFjdFRyYW5zZm9ybSh0aGlzLCB0c3RyKTtcblxuICAgICAgICB0aGlzLmNsaXAgJiYgJCh0aGlzLmNsaXAsIHt0cmFuc2Zvcm06IHRoaXMubWF0cml4LmludmVydCgpfSk7XG4gICAgICAgIHRoaXMucGF0dGVybiAmJiB1cGRhdGVQb3NpdGlvbih0aGlzKTtcbiAgICAgICAgdGhpcy5ub2RlICYmICQodGhpcy5ub2RlLCB7dHJhbnNmb3JtOiB0aGlzLm1hdHJpeH0pO1xuXG4gICAgICAgIGlmIChfLnN4ICE9IDEgfHwgXy5zeSAhPSAxKSB7XG4gICAgICAgICAgICB2Y
57601XIgc3cgPSB0aGlzLmF0dHJzW2hhc10oXCJzdHJva2Utd2lkdGhcIikgPyB0aGlzLmF0dHJzW1wic3Ryb2tlLXdpZHRoXCJdIDogMTtcbiAgICAgICAgICAgIHRoaXMuYXR0cih7XCJzdHJva2Utd2lkdGhcIjogc3d9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuaGlkZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogTWFrZXMgZWxlbWVudCBpbnZpc2libGUuIFNlZSBARWxlbWVudC5zaG93LlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYoIXRoaXMucmVtb3ZlZCkgdGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5zaG93XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBNYWtlcyBlbGVtZW50IHZpc2libGUuIFNlZSBARWxlbWVudC5oaWRlLlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYoIXRoaXMucmVtb3ZlZCkgdGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnJlbW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBlbGVtZW50IGZyb20gdGhlIHBhcGVyLlxuICAgIFxcKi9cbiAgICBlbHByb3RvLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vZGUgPSBnZXRSZWFsTm9kZSh0aGlzLm5vZGUpO1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkIHx8ICFub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Y
57601XIgcGFwZXIgPSB0aGlzLnBhcGVyO1xuICAgICAgICBwYXBlci5fX3NldF9fICYmIHBhcGVyLl9fc2V0X18uZXhjbHVkZSh0aGlzKTtcbiAgICAgICAgZXZlLnVuYmluZChcInJhcGhhZWwuKi4qLlwiICsgdGhpcy5pZCk7XG4gICAgICAgIGlmICh0aGlzLmdyYWRpZW50KSB7XG4gICAgICAgICAgICBwYXBlci5kZWZzLnJlbW92ZUNoaWxkKHRoaXMuZ3JhZGllbnQpO1xuICAgICAgICB9XG4gICAgICAgIFIuX3RlYXIodGhpcywgcGFwZXIpO1xuXG4gICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblxuICAgICAgICAvLyBSZW1vdmUgY3VzdG9tIGRhdGEgZm9yIGVsZW1lbnRcbiAgICAgICAgdGhpcy5yZW1vdmVEYXRhKCk7XG5cbiAgICAgICAgZm9yICh2YXIgaSBpbiB0aGlzKSB7XG4gICAgICAgICAgICB0aGlzW2ldID0gdHlwZW9mIHRoaXNbaV0gPT0gXCJmdW5jdGlvblwiID8gUi5fcmVtb3ZlZEZhY3RvcnkoaSkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlZCA9IHRydWU7XG4gICAgfTtcbiAgICBlbHByb3RvLl9nZXRCQm94ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPT0gXCJub25lXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgdmFyIGhpZGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjYW52YXNIaWRkZW4gPSBmYWxzZSxcbiAgICAgICAgICAgIGNvbnRhaW5lclN0eWxlO1xuICAgICAgICBpZiAodGhpcy5wYXBlci
576015jYW52YXMucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgIGNvbnRhaW5lclN0eWxlID0gdGhpcy5wYXBlci5jYW52YXMucGFyZW50RWxlbWVudC5zdHlsZTtcbiAgICAgICAgfSAvL0lFMTArIGNhbid0IGZpbmQgcGFyZW50RWxlbWVudFxuICAgICAgICBlbHNlIGlmICh0aGlzLnBhcGVyLmNhbnZhcy5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgY29udGFpbmVyU3R5bGUgPSB0aGlzLnBhcGVyLmNhbnZhcy5wYXJlbnROb2RlLnN0eWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY29udGFpbmVyU3R5bGUgJiYgY29udGFpbmVyU3R5bGUuZGlzcGxheSA9PSBcIm5vbmVcIikge1xuICAgICAgICAgIGNhbnZhc0hpZGRlbiA9IHRydWU7XG4gICAgICAgICAgY29udGFpbmVyU3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJib3ggPSB7fTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGJib3ggPSB0aGlzLm5vZGUuZ2V0QkJveCgpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIC8vIEZpcmVmb3ggMy4wLngsIDI1LjAuMSAocHJvYmFibHkgbW9yZSB2ZXJzaW9ucyBhZmZlY3RlZCkgcGxheSBiYWRseSBoZXJlIC0gcG9zc2libGUgZml4XG4gICAgICAgICAgICBiYm94ID0ge1xuICAgICAgICAgICAgICAgIHg6IHRoaXMubm9kZS5jbGllbnRMZWZ0LFxuICAgICAgICAgICAgICAgIHk6IHRoaXMubm9kZS5jbGllbnRUb3AsXG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMubm9kZS5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMubm9kZS5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIGJib3ggPSBiYm94IHx8IHt9O1xuICAgICAgICAgICAgaWYoY2FudmFzSGlkZGVuKXtcbiAgICAgICAgICAgICAgY29udGFpbmVyU3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGhpZGUgJiYgdGhpcy5oaWRlKCk7XG4gICAgICAgIHJldHVybiBiYm94O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuYXR0clxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogU2V0cyB0aGUgYXR0cmlidXRlcyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gYXR0ck5hbWUgKHN0cmluZykgYXR0cmlidXRl4oCZcyBuYW1lXG4gICAgIC0gdmFsdWUgKHN0cmluZykgdmFsdWVcbiAgICAgKiBvclxuICAgICAtIHBhcmFtcyAob2JqZWN0KSBvYmplY3Qgb2YgbmFtZS92YWx1ZSBwYWlyc1xuICAgICAqIG9yXG4gICAgIC0gYXR0ck5hbWUgKHN0cmluZykgYXR0cmlidXRl4oCZcyBuYW1lXG4gICAgICogb3JcbiAgICAgLSBhdHRyTmFtZXMgKGFycmF5KSBpbiB0aGlzIGNhc2UgbWV0aG9kIHJldHVybnMgYXJyYXkgb2YgY3VycmVudCB2YWx1ZXMgZm9yIGdpdmVuIGF0dHJpYnV0ZSBuYW1lc1xuICAgICA9IChvYmplY3QpIEBFbGVtZW50IGlmIGF0dHJzTmFtZSAmIHZhbHVlIG9yIHBhcmFtcyBhcmUgcGFzc2VkIGluLlxuICAgICA9ICguLi4pIHZhbHVlIG9mIHRoZSBhdHRyaWJ1dGUgaWYgb25seSBhdHRyc05hbWUgaXMgcGFzc2VkIGluLlxuICAgICA9IChhcnJheSkgYXJyYXkgb2YgdmFsdWVzIG9mIHRoZSBhdHRyaWJ1dGUgaWYgYXR0cnNOYW1lcyBpcyBwYXNzZWQgaW4uXG4gICAgID0gKG9iamVjdCkgb2JqZWN0IG9mIGF0dHJpYnV0ZXMgaWYgbm90aGluZyBpcyBwYXNzZWQgaW4uXG4gICAgID4gUG9zc2libGUgcGFyYW1ldGVyc1xuICAgICAjIDxwPlBsZWFzZSByZWZlciB0byB0aGUgPGEgaHJlZj1cImh0dHA6Ly93d3cudzMub3JnL1RSL1NWRy9cIiB0aXRsZT1cIlRoZSBXM0MgUmVjb21tZW5kYXRpb24gZm9yIHRoZSBTVkcgbGFuZ3VhZ2UgZGVzY3JpYmVzIHRoZXNlIHByb3BlcnRpZXMgaW4gZGV0YWlsLlwiPlNWRyBzcGVjaWZpY2F0aW9uPC9hPiBmb3IgYW4gZXhwbGFuYXRpb24gb2YgdGhlc2UgcGFyYW1ldGVycy48L3A+XG4gICAgIG8gYXJyb3ctZW5kIChzdHJpbmcpIGFycm93aGVhZCBvbiB0aGUgZW5kIG9mIHRoZSBwYXRoLiBUaGUgZm9ybWF0IGZvciBzdHJpbmcgaXMgYDx0eXBlPlstPHdpZHRoPlstPGxlbmd0aD5dXWAuIFBvc3NpYmxlIHR5cGVzOiBgY2xhc3NpY2AsIGBibG9ja2AsIGBvcGVuYCwgYG92YWxgLCBgZGlhbW9uZGAsIGBub25lYCwgd2lkdGg6IGB3aWRlYCwgYG5hcnJvd2AsIGBtZWRpdW1gLCBsZW5ndGg6IGBsb25nYCwgYHNob3J0YCwgYG1pZGl1bWAuXG4gICAgIG8gY2xpcC1yZWN0IChzdHJpbmcpIGNvbW1hIG9yIHNwYWNlIHNlcGFyYXRlZCB2YWx1ZXM6IHgsIHksIHdpZHRoIGFuZCBoZWlnaHRcbiAgICAgbyBjdXJzb3IgKHN0cmluZykgQ1NTIHR5cGUgb2YgdGhlIGN1cnNvclxuICAgICBvIGN4IChudW1iZXIpIHRoZSB4LWF4aXMgY29vcmRpbmF0ZSBvZiB0aGUgY2VudGVyIG9mIHRoZSBjaXJjbGUsIG9yIGVsbGlwc2VcbiAgICAgbyBjeSAobnVtYmVyKSB0aGUgeS1heGlzIGNvb3JkaW5hdGUgb2YgdGhlIGNlbnRlciBvZiB0aGUgY2lyY2xlLCBvciBlbGxpcHNlXG4gICAgIG8gZmlsbCAoc3RyaW5nKSBjb2xvdXIsIGdyYWRpZW50IG9yIGltYWdlXG4gICAgIG8gZmlsbC1vcGFjaXR5IChudW1iZXIpXG4gICAgIG8gZm9udCAoc3RyaW5nKVxuICAgICBvIGZvbnQtZmFtaWx5IChzdHJpbmcpXG4gICAgIG8gZm9udC1zaXplIChudW1iZXIpIGZvbnQgc2l6ZSBpbiBwaXhlbHNcbiAgICAgbyBmb250LXdlaWdodCAoc3RyaW5nKVxuICAgICBvIGhlaWdodCAobnVtYmVyKVxuICAgICBvIGhyZWYgKHN0cmluZykgVVJMLCBpZiBzcGVjaWZpZWQgZWxlbWVudCBiZWhhdmVzIGFzIGh5cGVybGlua1xuICAgICBvIG9wYWNpdHkgKG51bWJlcilcbiAgICAgbyBwYXRoIChzdHJpbmcpIFNWRyBwYXRoIHN0cmluZyBmb3JtYXRcbiAgICAgbyByIChudW1iZXIpIHJhZGl1cyBvZiB0aGUgY2lyY2xlLCBlbGxpcHNlIG9yIHJvdW5kZWQgY29ybmVyIG9uIHRoZSByZWN0XG4gICAgIG8gcnggKG51bWJlcikgaG9yaXNvbnRhbCByYWRpdXMgb2YgdGhlIGVsbGlwc2VcbiAgICAgbyByeSAobnVtYmVyKSB2ZXJ0aWNhbCByYWRpdXMgb2YgdGhlIGVsbGlwc2VcbiAgICAgbyBzcmMgKHN0cmluZykgaW1hZ2UgVVJMLCBvbmx5IHdvcmtzIGZvciBARWxlbWVudC5pbWFnZSBlbGVtZW50XG4gICAgIG8gc3Ryb2tlIChzdHJpbmcpIHN0cm9rZSBjb2xvdXJcbiAgICAgbyBzdHJva2UtZGFzaGFycmF5IChzdHJpbmcpIFvigJzigJ0sIOKAnG5vbmXigJ0sIOKAnGAtYOKAnSwg4oCcYC5g4oCdLCDigJxgLS5g4oCdLCDigJxgLS4uYOKAnSwg4oCcYC4gYOKAnSwg4oCcYC0gYOKAnSwg4oCcYC0tYOKAnSwg4oCcYC0gLmDigJ0sIOKAnGAtLS5g4oCdLCDigJxgLS0uLmDigJ1dXG4gICAgIG8gc3Ryb2tlLWxpbmVjYXAgKHN0cmluZykgW+KAnGBidXR0YOKAnSwg4oCcYHNxdWFyZWDigJ0sIOKAnGByb3VuZGDigJ1dXG4gICAgIG8gc3Ryb2tlLWxpbmVqb2luIChzdHJpbmcpIFvigJxgYmV2ZWxg4oCdLCDigJxgcm91bmRg4oCdLCDigJxgbWl0ZXJg4oCdXVxuICAgICBvIHN0cm9rZS1taXRlcmxpbWl0IChudW1iZXIpXG4gICAgIG8gc3Ryb2tlLW9wYWNpdHkgKG51bWJlcilcbiAgICAgbyBzdHJva2Utd2lkdGggKG51bWJlcikgc3Ryb2tlIHdpZHRoIGluIHBpeGVscywgZGVmYXVsdCBpcyAnMSdcbiAgICAgbyB0YXJnZXQgKHN0cmluZykgdXNlZCB3aXRoIGhyZWZcbiAgICAgbyB0ZXh0IChzdHJpbmcpIGNvbnRlbn
57601RzIG9mIHRoZSB0ZXh0IGVsZW1lbnQuIFVzZSBgXFxuYCBmb3IgbXVsdGlsaW5lIHRleHRcbiAgICAgbyB0ZXh0LWFuY2hvciAoc3RyaW5nKSBb4oCcYHN0YXJ0YOKAnSwg4oCcYG1pZGRsZWDigJ0sIOKAnGBlbmRg4oCdXSwgZGVmYXVsdCBpcyDigJxgbWlkZGxlYOKAnVxuICAgICBvIHRpdGxlIChzdHJpbmcpIHdpbGwgY3JlYXRlIHRvb2x0aXAgd2l0aCBhIGdpdmVuIHRleHRcbiAgICAgbyB0cmFuc2Zvcm0gKHN0cmluZykgc2VlIEBFbGVtZW50LnRyYW5zZm9ybVxuICAgICBvIHdpZHRoIChudW1iZXIpXG4gICAgIG8geCAobnVtYmVyKVxuICAgICBvIHkgKG51bWJlcilcbiAgICAgPiBHcmFkaWVudHNcbiAgICAgKiBMaW5lYXIgZ3JhZGllbnQgZm9ybWF0OiDigJxg4oC5YW5nbGXigLot4oC5Y29sb3Vy4oC6Wy3igLljb2xvdXLigLpbOuKAuW9mZnNldOKAul1dKi3igLljb2xvdXLigLpg4oCdLCBleGFtcGxlOiDigJxgOTAtI2ZmZi0jMDAwYOKAnSDigJMgOTDCsFxuICAgICAqIGdyYWRpZW50IGZyb20gd2hpdGUgdG8gYmxhY2sgb3Ig4oCcYDAtI2ZmZi0jZjAwOjIwLSMwMDBg4oCdIOKAkyAwwrAgZ3JhZGllbnQgZnJvbSB3aGl0ZSB2aWEgcmVkIChhdCAyMCUpIHRvIGJsYWNrLlxuICAgICAqXG4gICAgICogcmFkaWFsIGdyYWRpZW50OiDigJxgclso4oC5ZnjigLosIOKAuWZ54oC6KV3igLljb2xvdXLigLpbLeKAuWNvbG91cuKAuls64oC5b2Zmc2V04oC6XV0qLeKAuWNvbG91cuKAumDigJ0sIGV4YW1wbGU6IOKAnGByI2ZmZi0jMDAwYOKAnSDigJNcbiAgICAgKiBncmFkaWVudCBmcm9tIHdoaXRlIHRvIGJsYWNrIG9yIOKAnGByKDAuMjUsIDAuNzUpI2ZmZi0jMDAwYOKAnSDigJMgZ3JhZGllbnQgZnJvbSB3aGl0ZSB0byBibGFjayB3aXRoIGZvY3VzIHBvaW50XG4gICAgICogYXQgMC4yNSwgMC43NS4gRm9jdXMgcG9pbnQgY29vcmRpbmF0ZXMgYXJlIGluIDAuLjEgcmFuZ2UuIFJhZGlhbCBncmFkaWVudHMgY2FuIG9ubHkgYmUgYXBwbGllZCB0byBjaXJjbGVzIGFuZCBlbGxpcHNlcy5cbiAgICAgPiBQYXRoIFN0cmluZ1xuICAgICAjIDxwPlBsZWFzZSByZWZlciB0byA8YSBocmVmPVwiaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHL3BhdGhzLmh0bWwjUGF0aERhdGFcIiB0aXRsZT1cIkRldGFpbHMgb2YgYSBwYXRo4oCZcyBkYXRhIGF0dHJpYnV0ZeKAmXMgZm9ybWF0IGFyZSBkZXNjcmliZWQgaW4gdGhlIFNWRyBzcGVjaWZpY2F0aW9uLlwiPlNWRyBkb2N1bWVudGF0aW9uIHJlZ2FyZGluZyBwYXRoIHN0cmluZzwvYT4uIFJhcGhhw6tsIGZ1bGx5IHN1cHBvcnRzIGl0LjwvcD5cbiAgICAgPiBDb2xvdXIgUGFyc2luZ1xuICAgICAjIDx1bD5cbiAgICAgIyAgICAgPGxpPkNvbG91ciBuYW1lICjigJw8Y29kZT5yZWQ8L2NvZGU+4oCdLCDigJw8Y29kZT5ncmVlbjwvY29kZT7igJ0sIOKAnDxjb2RlPmNvcm5mbG93ZXJibHVlPC9jb2RlPuKAnSwgZXRjKTwvbGk+XG4gICAgICMgICAgIDxsaT4j4oCi4oCi4oCiIOKAlCBzaG9ydGVuZWQgSFRNTCBjb2xvdXI6ICjigJw8Y29kZT4jMDAwPC9jb2RlPuKAnSwg4oCcPGNvZGU+I2ZjMDwvY29kZT7igJ0sIGV0Yyk8L2xpPlxuICAgICAjICAgICA8bGk+I+KAouKAouKAouKAouKAouKAoiDigJQgZnVsbCBsZW5ndGggSFRNTCBjb2xvdXI6ICjigJw8Y29kZT4jMDAwMDAwPC9jb2RlPuKAnSwg4oCcPGNvZGU+I2JkMjMwMDwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPnJnYijigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgcmVkLCBncmVlbiBhbmQgYmx1ZSBjaGFubmVsc+KAmSB2YWx1ZXM6ICjigJw8Y29kZT5yZ2IoMjAwLCZuYnNwOzEwMCwmbmJzcDswKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPnJnYijigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU6ICjigJw8Y29kZT5yZ2IoMTAwJSwmbmJzcDsxNzUlLCZuYnNwOzAlKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPnJnYmEo4oCi4oCi4oCiLCDigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgcmVkLCBncmVlbiBhbmQgYmx1ZSBjaGFubmVsc+KAmSB2YWx1ZXM6ICjigJw8Y29kZT5yZ2JhKDIwMCwmbmJzcDsxMDAsJm5ic3A7MCwgLjUpPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+cmdiYSjigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU6ICjigJw8Y29kZT5yZ2JhKDEwMCUsJm5ic3A7MTc1JSwmbmJzcDswJSwgNTAlKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPmhzYijigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgaHVlLCBzYXR1cmF0aW9uIGFuZCBicmlnaHRuZXNzIHZhbHVlczogKOKAnDxjb2RlPmhzYigwLjUsJm5ic3A7MC4yNSwmbmJzcDsxKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPmhzYijigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU8L2xpPlxuICAgICAjICAgICA8bGk+aHNiYSjigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgd2l0aCBvcGFjaXR5PC9saT5cbiAgICAgIyAgICAgPGxpPmhzbCjigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgYWxtb3N0IHRoZSBzYW1lIGFzIGhzYiwgc2VlIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0hTTF9hbmRfSFNWXCIgdGl0bGU9XCJIU0wgYW5kIEhTViAtIFdpa2lwZWRpYSwgdGhlIGZyZWUgZW5jeWNsb3BlZGlhXCI+V2lraXBlZGlhIHBhZ2U8L2E+PC9saT5cbiAgICAgIyAgICAgPGxpPmhzbCjigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU8L2xpPlxuICAgICAjICAgICA8bGk+aHNsYSjigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgd2l0aCBvcGFjaXR5PC9saT5cbiAgICAgIyAgICAgPGxpPk9wdGlvbmFsbHkgZm9yIGhzYiBhbmQgaHNsIHlvdSBjb3VsZCBzcGVjaWZ5IGh1ZSBhcyBhIGRlZ3JlZTog4oCcPGNvZGU+aHNsKDI0MGRlZywmbmJzcDsxLCZuYnNwOy41KTwvY29kZT7igJ0gb3IsIGlmIHlvdSB3YW50IHRvIGdvIGZhbmN5LCDigJw8Y29kZT5oc2woMjQwwrAsJm5ic3A7MSwmbmJzcDsuNSk8L2NvZGU+4oCdPC9saT5cbiAgICAgIyA8L3VsPlxuICAgIFxcKi9cbiAgICBlbHByb3RvLmF0dHIgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgI
57601H1cbiAgICAgICAgaWYgKG5hbWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgYSBpbiB0aGlzLmF0dHJzKSBpZiAodGhpcy5hdHRyc1toYXNdKGEpKSB7XG4gICAgICAgICAgICAgICAgcmVzW2FdID0gdGhpcy5hdHRyc1thXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcy5ncmFkaWVudCAmJiByZXMuZmlsbCA9PSBcIm5vbmVcIiAmJiAocmVzLmZpbGwgPSByZXMuZ3JhZGllbnQpICYmIGRlbGV0ZSByZXMuZ3JhZGllbnQ7XG4gICAgICAgICAgICByZXMudHJhbnNmb3JtID0gdGhpcy5fLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwgJiYgUi5pcyhuYW1lLCBcInN0cmluZ1wiKSkge1xuICAgICAgICAgICAgaWYgKG5hbWUgPT0gXCJmaWxsXCIgJiYgdGhpcy5hdHRycy5maWxsID09IFwibm9uZVwiICYmIHRoaXMuYXR0cnMuZ3JhZGllbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hdHRycy5ncmFkaWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuYW1lID09IFwidHJhbnNmb3JtXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBuYW1lcyA9IG5hbWUuc3BsaXQoc2VwYXJhdG9yKSxcbiAgICAgICAgICAgICAgICBvdXQgPSB7fTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG5hbWVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBuYW1lID0gbmFtZXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKG5hbWUgaW4gdGhpcy5hdHRycykge1xuICAgICAgICAgICAgICAgICAgICBvdXRbbmFtZV0gPSB0aGlzLmF0dHJzW25hbWVdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoUi5pcyh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbbmFtZV0sIFwiZnVuY3Rpb25cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0W25hbWVdID0gdGhpcy5wYXBlci
576015jdXN0b21BdHRyaWJ1dGVzW25hbWVdLmRlZjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRbbmFtZV0gPSBSLl9hdmFpbGFibGVBdHRyc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaWkgLSAxID8gb3V0IDogb3V0W25hbWVzWzBdXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCAmJiBSLmlzKG5hbWUsIFwiYXJyYXlcIikpIHtcbiAgICAgICAgICAgIG91dCA9IHt9O1xuICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBuYW1lLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvdXRbbmFtZVtpXV0gPSB0aGlzLmF0dHIobmFtZVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgcGFyYW1zID0ge307XG4gICAgICAgICAgICBwYXJhbXNbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChuYW1lICE9IG51bGwgJiYgUi5pcyhuYW1lLCBcIm9iamVjdFwiKSkge1xuICAgICAgICAgICAgcGFyYW1zID0gbmFtZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmF0dHIuXCIgKyBrZXkgKyBcIi5cIiArIHRoaXMuaWQsIHRoaXMsIHBhcmFtc1trZXldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGtleSBpbiB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXMpIGlmICh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbaGFzXShrZXkpICYmIHBhcmFtc1toYXNdKGtleSkgJiYgUi5pcyh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNba2V5XSwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgdmFyIHBhciA9IHRoaXMucGFwZXIuY3VzdG9tQXR0cmlidXRlc1trZXldLmFwcGx5KHRoaXMsIFtdLmNvbmNhdChwYXJhbXNba2V5XSkpO1xuICAgICAgICAgICAgdGhpcy5hdHRyc1trZXldID0gcGFyYW1zW2tleV07XG4gICAgICAgICAgICBmb3IgKHZhciBzdWJrZXkgaW4gcGFyKSBpZiAocGFyW2hhc10oc3Via2V5KSkge1xuICAgICAgICAgICAgICAgIHBhcmFtc1tzdWJrZXldID0gcGFyW3N1YmtleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2V0RmlsbEFuZFN0cm9rZSh0aGlzLCBwYXJhbXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnRvRnJvbnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIE1vdmVzIHRoZSBlbGVtZW50IHNvIGl0IGlzIHRoZSBjbG9zZXN0IHRvIHRoZSB2aWV3ZXLigJlzIGV5ZXMsIG9uIHRvcCBvZiBvdGhlciBlbGVtZW50cy5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRvRnJvbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub2RlID0gZ2V0UmVhbE5vZGUodGhpcy5ub2RlKTtcbiAgICAgICAgbm9kZS5wYXJlbnROb2RlLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgICB2Y
57601XIgc3ZnID0gdGhpcy5wYXBlcjtcbiAgICAgICAgc3ZnLnRvcCAhPSB0aGlzICYmIFIuX3RvZnJvbnQodGhpcywgc3ZnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC50b0JhY2tcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIE1vdmVzIHRoZSBlbGVtZW50IHNvIGl0IGlzIHRoZSBmdXJ0aGVzdCBmcm9tIHRoZSB2aWV3ZXLigJlzIGV5ZXMsIGJlaGluZCBvdGhlciBlbGVtZW50cy5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRvQmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5vZGUgPSBnZXRSZWFsTm9kZSh0aGlzLm5vZGUpO1xuICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IG5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgcGFyZW50Tm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgUi5fdG9iYWNrKHRoaXMsIHRoaXMucGFwZXIpO1xuICAgICAgICB2YXIgc3ZnID0gdGhpcy5wYXBlcjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5pbnNlcnRBZnRlclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogSW5zZXJ0cyBjdXJyZW50IG9iamVjdCBhZnRlciB0aGUgZ2l2ZW4gb25lLlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaW5zZXJ0QWZ0ZXIgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkIHx8ICFlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBub2RlID0gZ2V0UmVhbE5vZGUodGhpcy5ub2RlKTtcbiAgICAgICAgdmFyIGFmdGVyTm9kZSA9IGdldFJlYWxOb2RlKGVsZW1lbnQubm9kZSB8fCBlbGVtZW50W2VsZW1lbnQubGVuZ3RoIC0gMV0ubm9kZSk7XG4gICAgICAgIGlmIChhZnRlck5vZGUubmV4dFNpYmxpbmcpIHtcbiAgICAgICAgICAgIGFmdGVyTm9kZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShub2RlLCBhZnRlck5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWZ0ZXJOb2RlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgUi5faW5zZXJ0YWZ0ZXIodGhpcywgZWxlbWVudCwgdGhpcy5wYXBlcik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuaW5zZXJ0QmVmb3JlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJbnNlcnRzIGN1cnJlbnQgb2JqZWN0IGJlZm9yZSB0aGUgZ2l2ZW4gb25lLlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaW5zZXJ0QmVmb3JlID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCB8fCAhZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICB2Y
57601XIgbm9kZSA9IGdldFJlYWxOb2RlKHRoaXMubm9kZSk7XG4gICAgICAgIHZhciBiZWZvcmVOb2RlID0gZ2V0UmVhbE5vZGUoZWxlbWVudC5ub2RlIHx8IGVsZW1lbnRbMF0ubm9kZSk7XG4gICAgICAgIGJlZm9yZU5vZGUucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgYmVmb3JlTm9kZSk7XG4gICAgICAgIFIuX2luc2VydGJlZm9yZSh0aGlzLCBlbGVtZW50LCB0aGlzLnBhcGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmJsdXIgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICAvLyBFeHBlcmltZW50YWwuIE5vIFNhZmFyaSBzdXBwb3J0LiBVc2UgaXQgb24geW91ciBvd24gcmlzay5cbiAgICAgICAgdmFyIHQgPSB0aGlzO1xuICAgICAgICBpZiAoK3NpemUgIT09IDApIHtcbiAgICAgICAgICAgIHZhciBmbHRyID0gJChcImZpbHRlclwiKSxcbiAgICAgICAgICAgICAgICBibHVyID0gJChcImZlR2F1c3NpYW5CbHVyXCIpO1xuICAgICAgICAgICAgdC5hdHRycy5ibHVyID0gc2l6ZTtcbiAgICAgICAgICAgIGZsdHIuaWQgPSBSLmNyZWF0ZVVVSUQoKTtcbiAgICAgICAgICAgICQoYmx1ciwge3N0ZERldmlhdGlvbjogK3NpemUgfHwgMS41fSk7XG4gICAgICAgICAgICBmbHRyLmFwcGVuZENoaWxkKGJsdXIpO1xuICAgICAgICAgICAgdC5wYXBlci5kZWZzLmFwcGVuZENoaWxkKGZsdHIpO1xuICAgICAgICAgICAgdC5fYmx1ciA9IGZsdHI7XG4gICAgICAgICAgICAkKHQubm9kZSwge2ZpbHRlcjogXCJ1cmwoI1wiICsgZmx0ci5pZCArIFwiKVwifSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodC5fYmx1cikge1xuICAgICAgICAgICAgICAgIHQuX2JsdXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0Ll9ibHVyKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdC5fYmx1cjtcbiAgICAgICAgICAgICAgICBkZWxldGUgdC5hdHRycy5ibHVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdC5ub2RlLnJlbW92ZUF0dHJpYnV0ZShcImZpbHRlclwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5jaXJjbGUgPSBmdW5jdGlvbiAoc3ZnLCB4LCB5LCByKSB7XG4gICAgICAgIHZhciBlbCA9ICQoXCJjaXJjbGVcIik7XG4gICAgICAgIHN2Zy5jYW52YXMgJiYgc3ZnLmNhbnZhcy5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIHZhciByZXMgPSBuZXcgRWxlbWVudChlbCwgc3ZnKTtcbiAgICAgICAgcmVzLmF0dHJzID0ge2N4OiB4LCBjeTogeSwgcjogciwgZmlsbDogXCJub25lXCIsIHN0cm9rZTogXCIjMDAwXCJ9O1xuICAgICAgICByZXMudHlwZSA9IFwiY2lyY2xlXCI7XG4gICAgICAgICQoZWwsIHJlcy5hdHRycyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUucmVjdCA9IGZ1bmN0aW9uIChzdmcsIHgsIHksIHcsIGgsIHIpIHtcbiAgICAgICAgdmFyIGVsID0gJChcInJlY3RcIik7XG4gICAgICAgIHN2Zy5jYW52YXMgJiYgc3ZnLmNhbnZhcy5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIHZhciByZXMgPSBuZXcgRWxlbWVudChlbCwgc3ZnKTtcbiAgICAgICAgcmVzLmF0dHJzID0ge3g6IHgsIHk6IHksIHdpZHRoOiB3LCBoZWlnaHQ6IGgsIHJ4OiByIHx8IDAsIHJ5OiByIHx8IDAsIGZpbGw6IFwibm9uZVwiLCBzdHJva2U6IFwiIzAwMFwifTtcbiAgICAgICAgcmVzLnR5cGUgPSBcInJlY3RcIjtcbiAgICAgICAgJChlbCwgcmVzLmF0dHJzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5lbGxpcHNlID0gZnVuY3Rpb24gKHN2ZywgeCwgeSwgcngsIHJ5KSB7XG4gICAgICAgIHZhciBlbCA9ICQoXCJlbGxpcHNlXCIpO1xuICAgICAgICBzdmcuY2FudmFzICYmIHN2Zy5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2Y
57601XIgcmVzID0gbmV3IEVsZW1lbnQoZWwsIHN2Zyk7XG4gICAgICAgIHJlcy5hdHRycyA9IHtjeDogeCwgY3k6IHksIHJ4OiByeCwgcnk6IHJ5LCBmaWxsOiBcIm5vbmVcIiwgc3Ryb2tlOiBcIiMwMDBcIn07XG4gICAgICAgIHJlcy50eXBlID0gXCJlbGxpcHNlXCI7XG4gICAgICAgICQoZWwsIHJlcy5hdHRycyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuaW1hZ2UgPSBmdW5jdGlvbiAoc3ZnLCBzcmMsIHgsIHksIHcsIGgpIHtcbiAgICAgICAgdmFyIGVsID0gJChcImltYWdlXCIpO1xuICAgICAgICAkKGVsLCB7eDogeCwgeTogeSwgd2lkdGg6IHcsIGhlaWdodDogaCwgcHJlc2VydmVBc3BlY3RSYXRpbzogXCJub25lXCJ9KTtcbiAgICAgICAgZWwuc2V0QXR0cmlidXRlTlMoeGxpbmssIFwiaHJlZlwiLCBzcmMpO1xuICAgICAgICBzdmcuY2FudmFzICYmIHN2Zy5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2YXIgcmVzID0gbmV3IEVsZW1lbnQoZWwsIHN2Zyk7XG4gICAgICAgIHJlcy5hdHRycyA9IHt4OiB4LCB5OiB5LCB3aWR0aDogdywgaGVpZ2h0OiBoLCBzcmM6IHNyY307XG4gICAgICAgIHJlcy50eXBlID0gXCJpbWFnZVwiO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLnRleHQgPSBmdW5jdGlvbiAoc3ZnLCB4LCB5LCB0ZXh0KSB7XG4gICAgICAgIHZhciBlbCA9ICQoXCJ0ZXh0XCIpO1xuICAgICAgICBzdmcuY2FudmFzICYmIHN2Zy5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2Y
57601XIgcmVzID0gbmV3IEVsZW1lbnQoZWwsIHN2Zyk7XG4gICAgICAgIHJlcy5hdHRycyA9IHtcbiAgICAgICAgICAgIHg6IHgsXG4gICAgICAgICAgICB5OiB5LFxuICAgICAgICAgICAgXCJ0ZXh0LWFuY2hvclwiOiBcIm1pZGRsZVwiLFxuICAgICAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgICAgIFwiZm9udC1mYW1pbHlcIjogUi5fYXZhaWxhYmxlQXR0cnNbXCJmb250LWZhbWlseVwiXSxcbiAgICAgICAgICAgIFwiZm9udC1zaXplXCI6IFIuX2F2YWlsYWJsZUF0dHJzW1wiZm9udC1zaXplXCJdLFxuICAgICAgICAgICAgc3Ryb2tlOiBcIm5vbmVcIixcbiAgICAgICAgICAgIGZpbGw6IFwiIzAwMFwiXG4gICAgICAgIH07XG4gICAgICAgIHJlcy50eXBlID0gXCJ0ZXh0XCI7XG4gICAgICAgIHNldEZpbGxBbmRTdHJva2UocmVzLCByZXMuYXR0cnMpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLnNldFNpemUgPSBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCkge1xuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGggfHwgdGhpcy53aWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQgfHwgdGhpcy5oZWlnaHQ7XG4gICAgICAgIHRoaXMuY2FudmFzLnNldEF0dHJpYnV0ZShcIndpZHRoXCIsIHRoaXMud2lkdGgpO1xuICAgICAgICB0aGlzLmNhbnZhcy5zZXRBdHRyaWJ1dGUoXCJoZWlnaHRcIiwgdGhpcy5oZWlnaHQpO1xuICAgICAgICBpZiAodGhpcy5fdmlld0JveCkge1xuICAgICAgICAgICAgdGhpcy5zZXRWaWV3Qm94LmFwcGx5KHRoaXMsIHRoaXMuX3ZpZXdCb3gpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLmNyZWF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbiA9IFIuX2dldENvbnRhaW5lci5hcHBseSgwLCBhcmd1bWVudHMpLFxuICAgICAgICAgICAgY29udGFpbmVyID0gY29uICYmIGNvbi5jb250YWluZXI7XG4gICAgICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTVkcgY29udGFpbmVyIG5vdCBmb3VuZC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHggPSBjb24ueCxcbiAgICAgICAgICAgIHkgPSBjb24ueSxcbiAgICAgICAgICAgIHdpZHRoID0gY29uLndpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0ID0gY29uLmhlaWdodCxcbiAgICAgICAgICAgIGNudnMgPSAkKFwic3ZnXCIpLFxuICAgICAgICAgICAgY3NzID0gXCJvdmVyZmxvdzpoaWRkZW47XCIsXG4gICAgICAgICAgICBpc0Zsb2F0aW5nO1xuICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICB5ID0geSB8fCAwO1xuICAgICAgICB3aWR0aCA9IHdpZHRoIHx8IDUxMjtcbiAgICAgICAgaGVpZ2h0ID0gaGVpZ2h0IHx8IDM0MjtcbiAgICAgICAgJChjbnZzLCB7XG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHZlcnNpb246IDEuMSxcbiAgICAgICAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgICAgICAgIHhtbG5zOiBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXG4gICAgICAgICAgICBcInhtbG5zOnhsaW5rXCI6IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY29udGFpbmVyID09IDEpIHtcbiAgICAgICAgICAgIGNudnMuc3R5bGUuY3NzVGV4dCA9IGNzcyArIFwicG9zaXRpb246YWJzb2x1dGU7bGVmdDpcIiArIHggKyBcInB4O3RvcDpcIiArIHkgKyBcInB4XCI7XG4gICAgICAgICAgICBSLl9nLmRvYy5ib2R5LmFwcGVuZENoaWxkKGNudnMpO1xuICAgICAgICAgICAgaXNGbG9hdGluZyA9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjbnZzLnN0eWxlLmNzc1RleHQgPSBjc3MgKyBcInBvc2l0aW9uOnJlbGF0aXZlXCI7XG4gICAgICAgICAgICBpZiAoY29udGFpbmVyLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXIuaW5zZXJ0QmVmb3JlKGNudnMsIGNvbnRhaW5lci5maXJzdENoaWxkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGNudnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnRhaW5lciA9IG5ldyBSLl9QYXBlcjtcbiAgICAgICAgY29udGFpbmVyLndpZHR
57601oID0gd2lkdGg7XG4gICAgICAgIGNvbnRhaW5lci5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGNvbnRhaW5lci5jYW52YXMgPSBjbnZzO1xuICAgICAgICBjb250YWluZXIuY2xlYXIoKTtcbiAgICAgICAgY29udGFpbmVyLl9sZWZ0ID0gY29udGFpbmVyLl90b3AgPSAwO1xuICAgICAgICBpc0Zsb2F0aW5nICYmIChjb250YWluZXIucmVuZGVyZml4ID0gZnVuY3Rpb24gKCkge30pO1xuICAgICAgICBjb250YWluZXIucmVuZGVyZml4KCk7XG4gICAgICAgIHJldHVybiBjb250YWluZXI7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuc2V0Vmlld0JveCA9IGZ1bmN0aW9uICh4LCB5LCB3LCBoLCBmaXQpIHtcbiAgICAgICAgZXZlKFwicmFwaGFlbC5zZXRWaWV3Qm94XCIsIHRoaXMsIHRoaXMuX3ZpZXdCb3gsIFt4LCB5LCB3LCBoLCBmaXRdKTtcbiAgICAgICAgdmFyIHBhcGVyU2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxuICAgICAgICAgICAgc2l6ZSA9IG1tYXgodyAvIHBhcGVyU2l6ZS53aWR0aCwgaCAvIHBhcGVyU2l6ZS5oZWlnaHQpLFxuICAgICAgICAgICAgdG9wID0gdGhpcy50b3AsXG4gICAgICAgICAgICBhc3BlY3RSYXRpbyA9IGZpdCA/IFwieE1pZFlNaWQgbWVldFwiIDogXCJ4TWluWU1pblwiLFxuICAgICAgICAgICAgdmIsXG4gICAgICAgICAgICBzdztcbiAgICAgICAgaWYgKHggPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3ZiU2l6ZSkge1xuICAgICAgICAgICAgICAgIHNpemUgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX3ZiU2l6ZTtcbiAgICAgICAgICAgIHZiID0gXCIwIDAgXCIgKyB0aGlzLndpZHRoICsgUyArIHRoaXMuaGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fdmJTaXplID0gc2l6ZTtcbiAgICAgICAgICAgIHZiID0geCArIFMgKyB5ICsgUyArIHcgKyBTICsgaDtcbiAgICAgICAgfVxuICAgICAgICAkKHRoaXMuY2FudmFzLCB7XG4gICAgICAgICAgICB2aWV3Qm94OiB2YixcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86IGFzcGVjdFJhdGlvXG4gICAgICAgIH0pO1xuICAgICAgICB3aGlsZSAoc2l6ZSAmJiB0b3ApIHtcbiAgICAgICAgICAgIHN3ID0gXCJzdHJva2Utd2lkdGhcIiBpbiB0b3AuYX
57601R0cnMgPyB0b3AuYXR0cnNbXCJzdHJva2Utd2lkdGhcIl0gOiAxO1xuICAgICAgICAgICAgdG9wLmF0dHIoe1wic3Ryb2tlLXdpZHRoXCI6IHN3fSk7XG4gICAgICAgICAgICB0b3AuXy5kaXJ0eSA9IDE7XG4gICAgICAgICAgICB0b3AuXy5kaXJ0eVQgPSAxO1xuICAgICAgICAgICAgdG9wID0gdG9wLnByZXY7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmlld0JveCA9IFt4LCB5LCB3LCBoLCAhIWZpdF07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnJlbmRlcmZpeFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogRml4ZXMgdGhlIGlzc3VlIG9mIEZpcmVmb3ggYW5kIElFOSByZWdhcmRpbmcgc3VicGl4ZWwgcmVuZGVyaW5nLiBJZiBwYXBlciBpcyBkZXBlbmRlbnRcbiAgICAgKiBvbiBvdGhlciBlbGVtZW50cyBhZnRlciByZWZsb3cgaXQgY291bGQgc2hpZnQgaGFsZiBwaXhlbCB3aGljaCBjYXVzZSBmb3IgbGluZXMgdG8gbG9zdCB0aGVpciBjcmlzcG5lc3MuXG4gICAgICogVGhpcyBtZXRob2QgZml4ZXMgdGhlIGlzc3VlLlxuICAgICAqKlxuICAgICAgIFNwZWNpYWwgdGhhbmtzIHRvIE1hcml1c3ogTm93YWsgKGh0dHA6Ly93d3cubWVkaWtvby5jb20vKSBmb3IgdGhpcyBtZXRob2QuXG4gICAgXFwqL1xuICAgIFIucHJvdG90eXBlLnJlbmRlcmZpeCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNudnMgPSB0aGlzLmNhbnZhcyxcbiAgICAgICAgICAgIHMgPSBjbnZzLnN0eWxlLFxuICAgICAgICAgICAgcG9zO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcG9zID0gY252cy5nZXRTY3JlZW5DVE0oKSB8fCBjbnZzLmNyZWF0ZVNWR01hdHJpeCgpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBwb3MgPSBjbnZzLmNyZWF0ZVNWR01hdHJpeCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZWZ0ID0gLXBvcy5lICUgMSxcbiAgICAgICAgICAgIHRvcCA9IC1wb3MuZiAlIDE7XG4gICAgICAgIGlmIChsZWZ0IHx8IHRvcCkge1xuICAgICAgICAgICAgaWYgKGxlZnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sZWZ0ID0gKHRoaXMuX2xlZnQgKyBsZWZ0KSAlIDE7XG4gICAgICAgICAgICAgICAgcy5sZWZ0ID0gdGhpcy5fbGVmdCArIFwicHhcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0b3ApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl90b3AgPSAodGhpcy5fdG9wICsgdG9wKSAlIDE7XG4gICAgICAgICAgICAgICAgcy50b3AgPSB0aGlzLl90b3AgKyBcInB4XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5jbGVhclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ2xlYXJzIHRoZSBwYXBlciwgaS5lLiByZW1vdmVzIGFsbCB0aGUgZWxlbWVudHMuXG4gICAgXFwqL1xuICAgIFIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBSLmV2ZShcInJhcGhhZWwuY2xlYXJcIiwgdGhpcyk7XG4gICAgICAgIHZhciBjID0gdGhpcy5jYW52YXM7XG4gICAgICAgIHdoaWxlIChjLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgIGMucmVtb3ZlQ2hpbGQoYy5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJvdHRvbSA9IHRoaXMudG9wID0gbnVsbDtcbiAgICAgICAgKHRoaXMuZGVzYyA9ICQoXCJkZXNjXCIpKS5hcHBlbmRDaGlsZChSLl9nLmRvYy5jcmVhdGVUZXh0Tm9kZShcIkNyZWF0ZWQgd2l0aCBSYXBoYVxceGVibCBcIiArIFIudmVyc2lvbikpO1xuICAgICAgICBjLmFwcGVuZENoaWxkKHRoaXMuZGVzYyk7XG4gICAgICAgIGMuYXBwZW5kQ2hpbGQodGhpcy5kZWZzID0gJChcImRlZnNcIikpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnJlbW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyB0aGUgcGFwZXIgZnJvbSB0aGUgRE9NLlxuICAgIFxcKi9cbiAgICBSLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGV2ZShcInJhcGhhZWwucmVtb3ZlXCIsIHRoaXMpO1xuICAgICAgICB0aGlzLmNhbnZhcy5wYXJlbnROb2RlICYmIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMpIHtcbiAgICAgICAgICAgIHRoaXNbaV0gPSB0eXBlb2YgdGhpc1tpXSA9PSBcImZ1bmN0aW9uXCIgPyBSLl9yZW1vdmVkRmFjdG9yeShpKSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHZhciBzZXRwcm90byA9IFIuc3Q7XG4gICAgZm9yICh2YXIgbWV0aG9kIGluIGVscHJvdG8pIGlmIChlbHByb3RvW2hhc10obWV0aG9kKSAmJiAhc2V0cHJvdG9baGFzXShtZXRob2QpKSB7XG4gICAgICAgIHNldHByb3RvW21ldGhvZF0gPSAoZnVuY3Rpb24gKG1ldGhvZG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgICAgICBlbFttZXRob2RuYW1lXS5hcHBseShlbCwgYXJnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pKG1ldGhvZCk7XG4gICAgfVxufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./dev/raphael.svg.js\n");
57602
57603/***/ }),
57604
57605/***/ "./dev/raphael.vml.js":
57606/*!****************************!*\
57607  !*** ./dev/raphael.vml.js ***!
57608  \****************************/
57609/*! no static exports found */
57610/***/ (function(module, exports, __webpack_require__) {
57611
57612eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ \"./dev/raphael.core.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {\n    if (R && !R.vml) {\n        return;\n    }\n\n    var has = \"hasOwnProperty\",\n        Str = String,\n        toFloat = parseFloat,\n        math = Math,\n        round = math.round,\n        mmax = math.max,\n        mmin = math.min,\n        abs = math.abs,\n        fillString = \"fill\",\n        separator = /[, ]+/,\n        eve = R.eve,\n        ms = \" progid:DXImageTransform.Microsoft\",\n        S = \" \",\n        E = \"\",\n        map = {M: \"m\", L: \"l\", C: \"c\", Z: \"x\", m: \"t\", l: \"r\", c: \"v\", z: \"x\"},\n        bites = /([clmz]),?([^clmz]*)/gi,\n        blurregexp = / progid:\\S+Blur\\([^\\)]+\\)/g,\n        val = /-?[^,\\s-]+/g,\n        cssDot = \"position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)\",\n        zoom = 21600,\n        pathTypes = {path: 1, rect: 1, image: 1},\n        ovalTypes = {circle: 1, ellipse: 1},\n        path2vml = function (path) {\n            var total =  /[ahqstv]/ig,\n                command = R._pathToAbsolute;\n            Str(path).match(total) && (command = R._path2curve);\n            total = /[clmz]/g;\n            if (command == R._pathToAbsolute && !Str(path).match(total)) {\n                var res = Str(path).replace(bites, function (all, command, args) {\n                    var vals = [],\n                        isMove = command.toLowerCase() == \"m\",\n                        res = map[command];\n                    args.replace(val, function (value) {\n                        if (isMove && vals.length == 2) {\n                            res += vals + map[command == \"m\" ? \"l\" : \"L\"];\n                            vals = [];\n                        }\n                        vals.push(round(value * zoom));\n                    });\n                    return res + vals;\n                });\n                return res;\n            }\n            var pa = command(path), p, r;\n            res = [];\n            for (var i = 0, ii = pa.length; i < ii; i++) {\n                p = pa[i];\n                r = pa[i][0].toLowerCase();\n                r == \"z\" && (r = \"x\");\n                for (var j = 1, jj = p.length; j < jj; j++) {\n                    r += round(p[j] * zoom) + (j != jj - 1 ? \",\" : E);\n                }\n                res.push(r);\n            }\n            return res.join(S);\n        },\n        compensation = function (deg, dx, dy) {\n            var m = R.matrix();\n            m.rotate(-deg, .5, .5);\n            return {\n                dx: m.x(dx, dy),\n                dy: m.y(dx, dy)\n            };\n        },\n        setCoords = function (p, sx, sy, dx, dy, deg) {\n            var _ = p._,\n                m = p.matrix,\n                fillpos = _.fillpos,\n                o = p.node,\n                s = o.style,\n                y = 1,\n                flip = \"\",\n                dxdy,\n                kx = zoom / sx,\n                ky = zoom / sy;\n            s.visibility = \"hidden\";\n            if (!sx || !sy) {\n                return;\n            }\n            o.coordsize = abs(kx) + S + abs(ky);\n            s.rotation = deg * (sx * sy < 0 ? -1 : 1);\n            if (deg) {\n                var c = compensation(deg, dx, dy);\n                dx = c.dx;\n                dy = c.dy;\n            }\n            sx < 0 && (flip += \"x\");\n            sy < 0 && (flip += \" y\") && (y = -1);\n            s.flip = flip;\n            o.coordorigin = (dx * -kx) + S + (dy * -ky);\n            if (fillpos || _.fillsize) {\n                var fill = o.getElementsByTagName(fillString);\n                fill = fill && fill[0];\n                o.removeChild(fill);\n                if (fillpos) {\n                    c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));\n                    fill.position = c.dx * y + S + c.dy * y;\n                }\n                if (_.fillsize) {\n                    fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);\n                }\n                o.appendChild(fill);\n            }\n            s.visibility = \"visible\";\n        };\n    R.toString = function () {\n        return  \"Your browser doesn\\u2019t support SVG. Falling down to VML.\\nYou are running Rapha\\xebl \" + this.version;\n    };\n    var addArrow = function (o, value, isEnd) {\n        var values = Str(value).toLowerCase().split(\"-\"),\n            se = isEnd ? \"end\" : \"start\",\n            i = values.length,\n            type = \"classic\",\n            w = \"medium\",\n            h = \"medium\";\n        while (i--) {\n            switch (values[i]) {\n                case \"block\":\n                case \"classic\":\n                case \"oval\":\n                case \"diamond\":\n                case \"open\":\n                case \"none\":\n                    type = values[i];\n                    break;\n                case \"wide\":\n                case \"narrow\": h = values[i]; break;\n                case \"long\":\n                case \"short\": w = values[i]; break;\n            }\n        }\n        var stroke = o.node.getElementsByTagName(\"stroke\")[0];\n        stroke[se + \"arrow\"] = type;\n        stroke[se + \"arrowlength\"] = w;\n        stroke[se + \"arrowwidth\"] = h;\n    },\n    setFillAndStroke = function (o, params) {\n        // o.paper.canvas.style.display = \"none\";\n        o.attrs = o.attrs || {};\n        var node = o.node,\n            a = o.attrs,\n            s = node.style,\n            xy,\n            newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),\n            isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),\
57612n            res = o;\n\n\n        for (var par in params) if (params[has](par)) {\n            a[par] = params[par];\n        }\n        if (newpath) {\n            a.path = R._getPath[o.type](o);\n            o._.dirty = 1;\n        }\n        params.href && (node.href = params.href);\n        params.title && (node.title = params.title);\n        params.target && (node.target = params.target);\n        params.cursor && (s.cursor = params.cursor);\n        \"blur\" in params && o.blur(params.blur);\n        if (params.path && o.type == \"path\" || newpath) {\n            node.path = path2vml(~Str(a.path).toLowerCase().indexOf(\"r\") ? R._pathToAbsolute(a.path) : a.path);\n            o._.dirty = 1;\n            if (o.type == \"image\") {\n                o._.fillpos = [a.x, a.y];\n                o._.fillsize = [a.width, a.height];\n                setCoords(o, 1, 1, 0, 0, 0);\n            }\n        }\n        \"transform\" in params && o.transform(params.transform);\n        if (isOval) {\n            var cx = +a.cx,\n                cy = +a.cy,\n                rx = +a.rx || 
57612+a.r || 0,\n                ry = +a.ry || +a.r || 0;\n            node.path = R.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));\n            o._.dirty = 1;\n        }\n        if (\"clip-rect\" in params) {\n            var rect = Str(params[\"clip-rect\"]).split(separator);\n            if (rect.length == 4) {\n                rect[2] = +rect[2] + (+rect[0]);\n                rect[3] = +rect[3] + (+rect[1]);\n                var div = node.clipRect || R._g.doc.createElement(\"div\"),\n                    dstyle = div.style;\n                dstyle.clip = R.format(\"rect({1}px {2}px {3}px {0}px)\", rect);\n                if (!node.clipRect) {\n                    dstyle.position = \"absolute\";\n                    dstyle.top = 0;\n                    dstyle.left = 0;\n                    dstyle.width = o.paper.width + \"px\";\n                    dstyle.height = o.paper.height + \"px\";\n                    node.parentNode.insertBefore(div, node);\n                    div.appendChild(node);\n                    node.clipRect = div;\n                }\n            }\n            if (!params[\"clip-rect\"]) {\n                node.clipRect && (node.clipRect.style.clip = \"auto\");\n            }\n        }\n        if (o.textpath) {\n            var textpathStyle = o.textpath.style;\n            params.font && (textpathStyle.font = params.font);\n            params[\"font-family\"] && (textpathStyle.fontFamily = '\"' + params[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g, E) + '\"');\n            params[\"font-size\"] && (textpathStyle.fontSize = params[\"font-size\"]);\n            params[\"font-weight\"] && (textpathStyle.fontWeight = params[\"font-weight\"]);\n            params[\"font-style\"] && (textpathStyle.fontStyle = params[\"font-style\"]);\n        }\n        if (\"arrow-start\" in params) {\n            addArrow(res, params[\"arrow-start\"]);\n        }\n        if (\"arrow-end\" in params) {\n            addArrow(res, params[\"arrow-end\"], 1);\n        }\n        if (params.opacity != null ||\n            params.fill != null ||\n            params.src != null ||\n            params.stroke != null ||\n            params[\"stroke-width\"] != null ||\n            params[\"stroke-opacity\"] != null ||\n            params[\"fill-opacity\"] != null ||\n            params[\"stroke-dasharray\"] != null ||\n            params[\"stroke-miterlimit\"] != null ||\n            params[\"stroke-linejoin\"] != null ||\n            params[\"stroke-linecap\"] != null) {\n            var fill = node.getElementsByTagName(fillString),\n                newfill = false;\n            fill = fill && fill[0];\n            !fill && (newfill = fill = createNode(fillString));\n            if (o.type == \"image\" && params.src) {\n                fill.src = params.src;\n            }\n            params.fill && (fill.on = true);\n            if (fill.on == null || params.fill == \"none\" || params.fill === null) {\n                fill.on = false;\n            }\n            if (fill.on && params.fill) {\n                var isURL = Str(params.fill).match(R._ISURL);\n                if (isURL) {\n                    fill.parentNode == node && node.removeChild(fill);\n                    fill.rotate = true;\n                    fill.src = isURL[1];\n                    fill.type = \"tile\";\n                    var bbox = o.getBBox(1);\n                    fill.position = bbox.x + S + bbox.y;\n                    o._.fillpos = [bbox.x, bbox.y];\n\n                    R._preload(isURL[1], function () {\n                        o._.fillsize = [this.offsetWidth, this.offsetHeight];\n                    });\n                } else {\n                    fill.color = R.getRGB(params.fill).hex;\n                    fill.src = E;\n                    fill.type = \"solid\";\n                    if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != \"r\") && addGradientFill(res, params.fill, fill)) {\
57612n                        a.fill = \"none\";\n                        a.gradient = params.fill;\n                        fill.rotate = false;\n                    }\n                }\n            }\n            if (\"fill-opacity\" in params || \"opacity\" in params) {\n                var opacity = ((+a[\"fill-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);\n                opacity = mmin(mmax(opacity, 0), 1);\n                fill.opacity = opacity;\n                if (fill.src) {\n                    fill.color = \"none\";\n                }\n            }\n            node.appendChild(fill);\n            var stroke = (node.getElementsByTagName(\"stroke\") && node.getElementsByTagName(\"stroke\")[0]),\n            newstroke = false;\n            !stroke && (newstroke = stroke = createNode(\"stroke\"));\n            if ((params.stroke && params.stroke != \"none\") ||\n                params[\"stroke-width\"] ||\n                params[\"stroke-opacity\"] != null ||\n                params[\"stroke-dasharray\"] ||\n                params[\"stroke-miterlimit\"] ||\n                params[\"stroke-linejoin\"] ||\n                params[\"stroke-linecap\"]) {\n                stroke.on = true;\n            }\n            (params.stroke == \"none\" || params.stroke === null || stroke.on == null || params.stroke == 0 || params[\"stroke-width\"] == 0) && (stroke.on = false);\n            var strokeColor = R.getRGB(params.stroke);\n            stroke.on && params.stroke && (stroke.color = strokeColor.hex);\n            opacity = ((+a[\"stroke-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);\n            var width = (toFloat(params[\"stroke-width\"]) || 1) * .75;\n            opacity = mmin(mmax(opacity, 0), 1);\n            params[\"stroke-width\"] == null && (width = a[\"stroke-width\"]);\n            params[\"stroke-width\"] && (stroke.weight = width);\n            width && width < 1 && (opacity *= width) && (stroke.weight = 1);\n            stroke.opacity = opacity;\n\n            params[\"stroke-linejoin\"] && (stroke.joinstyle = params[\"stroke-linejoin\"] || \"miter\");\n            stroke.miterlimit = params[\"stroke-miterlimit\"] || 8;\n            params[\"stroke-linecap\"] && (stroke.endcap = params[\"stroke-linecap\"] == \"butt\" ? \"flat\" : params[\"stroke-linecap\"] == \"square\" ? \"square\" : \"round\");\n            if (\"stroke-dasharray\" in params) {\n                var dasharray = {\n                    \"-\": \"shortdash\",\n                    \".\": \"shortdot\",\n                    \"-.\": \"shortdashdot\",\n                    \"-..\": \"shortdashdotdot\",\n                    \". \": \"dot\",\n                    \"- \": \"dash\",\n                    \"--\": \"longdash\",\n                    \"- .\": \"dashdot\",\n                    \"--.\": \"longdashdot\",\n                    \"--..\": \"longdashdotdot\"\n                };\n                stroke.dashstyle = dasharray[has](params[\"stroke-dasharray\"]) ? dasharray[params[\"stroke-dasharray\"]] : E;\n            }\n            newstroke && node.appendChild(stroke);\n        }\n        if (res.type == \"text\") {\n            res.paper.canvas.style.display = E;\n            var span = res.paper.span,\n                m = 100,\n                fontSize = a.font && a.font.match(/\\d+(?:\\.\\d*)?(?=px)/);\n            s = span.style;\n            a.font && (s.font = a.font);\n            a[\"font-family\"] && (s.fontFamily = a[\"font-family\"]);\n            a[\"font-weight\"] && (s.fontWeight = a[\"font-weight\"]);\n            a[\"font-style\"] && (s.fontStyle = a[\"font-style\"]);\n            fontSize = toFloat(a[\"font-size\"] || fontSize && fontSize[0]) || 10;\n            s.fontSize = fontSize * m + \"px\";\n            res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, \"&#60;\").replace(/&/g, \"&#38;
57612\").replace(/\\n/g, \"<br>\"));\n            var brect = span.getBoundingClientRect();\n            res.W = a.w = (brect.right - brect.left) / m;\n            res.H = a.h = (brect.bottom - brect.top) / m;\n            // res.paper.canvas.style.display = \"none\";\n            res.X = a.x;\n            res.Y = a.y + res.H / 2;\n\n            (\"x\" in params || \"y\" in params) && (res.path.v = R.format(\"m{0},{1}l{2},{1}\", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));\n            var dirtyattrs = [\"x\", \"y\", \"text\", \"font\", \"font-family\", \"font-weight\", \"font-style\", \"font-size\"];\n            for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {\n                res._.dirty = 1;\n                break;\n            }\n\n            // text-anchor emulation\n            switch (a[\"text-anchor\"]) {\n                case \"start\":\n                    res.textpath.style[\"v-text-align\"] = \"left\";\n                    res.bbx = res.W / 2;\n                break;\n                case \"end\":\n                    res.textpath.style[\"v-text-align\"] = \"right\";\n                    res.bbx = -res.W / 2;\n                break;\n                default:\n                    res.textpath.style[\"v-text-align\"] = \"center\";\n                    res.bbx = 0;\n                break;\n            }\n            res.textpath.style[\"v-text-kern\"] = true;\n        }\n        // res.paper.canvas.style.display = E;\n    },\n    addGradientFill = function (o, gradient, fill) {\n        o.attrs = o.attrs || {};\n        var attrs = o.attrs,\n            pow = Math.pow,\n            opacity,\n            oindex,\n            type = \"linear\",\n            fxfy = \".5 .5\";\n        o.attrs.gradient = gradient;\n        gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {\n            type = \"radial\";\n            if (fx && fy) {\n                fx = toFloat(fx);\n                fy = toFloat(fy);\n                pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);\n                fxfy = fx + S + fy;\n            }\n            return E;\n        });\n        gradient = gradient.split(/\\s*\\-\\s*/);\n        if (type == \"linear\") {\n            var angle = gradient.shift();\n            angle = -toFloat(angle);\n            if (isNaN(angle)) {\n                return null;\n            }\n        }\n        var dots = R._parseDots(gradient);\n        if (!dots) {\n            return null;\n        }\n        o = o.shape || o.node;\n        if (dots.length) {\n            o.removeChild(fill);\n            fill.on = true;\n            fill.method = \"none\";\n            fill.color = dots[0].color;\n            fill.color2 = dots[dots.length - 1].color;\n            var clrs = [];\n            for (var i = 0, ii = dots.length; i < ii; i++) {\n                dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);\n            }\n            fill.colors = clrs.length ? clrs.join() : \"0% \" + fill.color;\n            if (type == \"radial\") {\n                fill.type = \"gradientTitle\";\n                fill.focus = \"100%\";\n                fill.focussize = \"0 0\";\n                fill.focusposition = fxfy;\n                fill.angle = 0;\n            } else {\n                // fill.rotate= true;\n                fill.type = \"gradient\";\n                fill.angle = (270 - angle) % 360;\n            }\n            o.appendChild(fill);\n        }\n        return 1;\n    },\n    Element = function (node, vml) {\n        this[0] = this.node = node;\n        node.raphael = true;\n        this.id = R._oid++;\n        node.raphaelid = this.id;\n        this.X = 0;\n        this.Y = 0;\n        this.attrs = {};\n        this.paper = vml;\n        this.matrix = R.matrix();\n        this._ = {\n            transform: [],\n            sx: 1,\n            sy: 1,\n            dx: 0,\n            dy: 0,\n            deg: 0,\n            dirty: 1,\n            dirtyT: 1\n        };\n        !vml.bottom && (vml.bottom = this);\n        this.prev = vml.top;\n        vml.top && (vml.top.next = this);\n        vml.top = this;\n        this.next = null;\n    };\n    var elproto = R.el;\n\n    Element.prototype = elproto;\n    elproto.constructor = Element;\n    elproto.transform = function (tstr) {\n        if (tstr == null) {\n            return this._.transform;\n        }\n        var vbs = this.paper._viewBoxShift,\n            vbt = vbs ? \"s\" + [vbs.scale, vbs.scale] + \"-1-1t\" + [vbs.dx, vbs.dy] : E,\n            oldt;\n        if (vbs) {\n            oldt = tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, this._.transform || E);\n        }\n        R._extractTransform(this, vbt + tstr);\n        var matrix = this.matrix.clone(),\n            skew = this.skew,\n            o = this.node,\n            split,\n            isGrad = ~Str(this.attrs.fill).indexOf(\"-\"),\n            isPatt = !Str(this.attrs.fill).indexOf(\"url(\");\n        matrix.translate(1, 1);\n        if (isPatt || isGrad || this.type == \"image\") {\n            skew.matrix = \"1 0 0 1\";\n            skew.offset = \"0 0\";\n            split = matrix.split();\n            if ((isGrad && split.noRotation) || !split.isSimple) {\n                o.style.filter = matrix.toFilter();\n                var bb = this.getBBox(),\n                    bbt = this.getBBox(1),\n                    dx = bb.x - bbt.x,\n                    dy = bb.y - bbt.y;\n                o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
57612\n                setCoords(this, 1, 1, dx, dy, 0);\n            } else {\n                o.style.filter = E;\n                setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);\n            }\n        } else {\n            o.style.filter = E;\n            skew.matrix = Str(matrix);\n            skew.offset = matrix.offset();\n        }\n        if (oldt !== null) { // empty string value is true as well\n            this._.transform = oldt;\n            R._extractTransform(this, oldt);\n        }\n        return this;\n    };\n    elproto.rotate = function (deg, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        if (deg == null) {\n            return;\n        }\n        deg = Str(deg).split(separator);\n        if (deg.length - 1) {\n            cx = toFloat(deg[1]);\n            cy = toFloat(deg[2]);\n        }\n        deg = toFloat(deg[0]);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n            cx = bbox.x + bbox.width / 2;\n            cy = bbox.y + bbox.height / 2;\n        }\n        this._.dirtyT = 1;\n        this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n        return this;\n    };\n    elproto.translate = function (dx, dy) {\n        if (this.removed) {\n            return this;\n        }\n        dx = Str(dx).split(separator);\n        if (dx.length - 1) {\n            dy = toFloat(dx[1]);\n        }\n        dx = toFloat(dx[0]) || 0;\n        dy = +dy || 0;\n        if (this._.bbox) {\n            this._.bbox.x += dx;\n            this._.bbox.y += dy;\n        }\n        this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n        return this;\n    };\n    elproto.scale = function (sx, sy, cx, cy) {\n        if (this.removed) {\n            return this;\n        }\n        sx = Str(sx).split(separator);\n        if (sx.length - 1) {\n            sy = toFloat(sx[1]);\n            cx = toFloat(sx[2]);\n            cy = toFloat(sx[3]);\n            isNaN(cx) && (cx = null);\n            isNaN(cy) && (cy = null);\n        }\n        sx = toFloat(sx[0]);\n        (sy == null) && (sy = sx);\n        (cy == null) && (cx = cy);\n        if (cx == null || cy == null) {\n            var bbox = this.getBBox(1);\n        }\n        cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n        cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n\n        this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n        this._.dirtyT = 1;\n        return this;\n    };\n    elproto.hide = function () {\n        !this.removed && (this.node.style.display = \"none\");\n        return this;\n    };\n    elproto.show = function () {\n        !this.removed && (this.node.style.display = E);\n        return this;\n    };\n    // Needed to fix the vml setViewBox issues\n    elproto.auxGetBBox = R.el.getBBox;\n    elproto.getBBox = function(){\n      var b = this.auxGetBBox();\n      if (this.paper && this.paper._viewBoxShift)\n      {\n        var c = {};\n        var z = 1/this.paper._viewBoxShift.scale;\n        c.x = b.x - this.paper._viewBoxShift.dx;\n        c.x *= z;\n        c.y = b.y - this.paper._viewBoxShift.dy;\n        c.y *= z;\n        c.width  = b.width  * z;
57612\n        c.height = b.height * z;\n        c.x2 = c.x + c.width;\n        c.y2 = c.y + c.height;\n        return c;\n      }\n      return b;\n    };\n    elproto._getBBox = function () {\n        if (this.removed) {\n            return {};\n        }\n        return {\n            x: this.X + (this.bbx || 0) - this.W / 2,\n            y: this.Y - this.H,\n            width: this.W,\n            height: this.H\n        };\n    };\n    elproto.remove = function () {\n        if (this.removed || !this.node.parentNode) {\n            return;\n        }\n        this.paper.__set__ && this.paper.__set__.exclude(this);\n        R.eve.unbind(\"raphael.*.*.\" + this.id);\n        R._tear(this, this.paper);\n        this.node.parentNode.removeChild(this.node);\n        this.shape && this.shape.parentNode.removeChild(this.shape);\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n        this.removed = true;\n    };\n    elproto.attr = function (name, value) {\n        if (this.removed) {\n            return this;\n        }\n        if (name == null) {\n            var res = {};\n            for (var a in this.attrs) if (this.attrs[has](a)) {\n                res[a] = this.attrs[a];\n            }\n            res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n            res.transform = this._.transform;\n            return res;\n        }\n        if (value == null && R.is(name, \"string\")) {\n            if (name == fillString && this.attrs.fill == \"none\" && this.attrs.gradient) {\n                return this.attrs.gradient;\n            }\n            var names = name.split(separator),\n                out = {};\n            for (var i = 0, ii = names.length; i < ii; i++) {\n                name = names[i];\n                if (name in this.attrs) {\n                    out[name] = this.attrs[name];\n                } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n                    out[name] = this.paper.customAttributes[name].def;\n                } else {\n                    out[name] = R._availableAttrs[name];\n                }\n            }\n            return ii - 1 ? out : out[names[0]];\n        }\n        if (this.attrs && value == null && R.is(name, \"array\")) {\n            out = {};\n            for (i = 0, ii = name.length; i < ii; i++) {\n                out[name[i]] = this.attr(name[i]);\n            }\n            return out;\n        }\n        var params;\n        if (value != null) {\n            params = {};\n            params[name] = value;\n        }\n        value == null && R.is(name, \"object\") && (params = name);\n        for (var key in params) {\n            eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n        }\n        if (params) {\n            for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n                var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n                this.attrs[key] = params[key];\n                for (var subkey in par) if (par[has](subkey)) {\n                    params[subkey] = par[subkey];\n                }\n            }\n            // this.paper.canvas.style.display = \"none\";\n            if (params.text && this.type == \"text\") {\n                this.textpath.string = params.text;\n            }\n            setFillAndStroke(this, params);\n            // this.paper.canvas.style.display = E;\n        }\n        return this;\n    };\n    elproto.toFront = function () {\n        !this.removed && this.node.parentNode.appendChild(this.node);\n        this.paper && this.paper.top != this && R._tofront(this, this.paper);\n        return this;\n    };\n    elproto.toBack = function () {\n        if (this.removed) {\n            return this;\n        }\n        if (this.node.parentNode.firstChild != this.node) {\n            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);\n            R._toback(this, this.paper);\n        }\n        return this;\n    };\n    elproto.insertAfter = function (element) {\n        if (this.removed) {\
57612n            return this;\n        }\n        if (element.constructor == R.st.constructor) {\n            element = element[element.length - 1];\n        }\n        if (element.node.nextSibling) {\n            element.node.parentNode.insertBefore(this.node, element.node.nextSibling);\n        } else {\n            element.node.parentNode.appendChild(this.node);\n        }\n        R._insertafter(this, element, this.paper);\n        return this;\n    };\n    elproto.insertBefore = function (element) {\n        if (this.removed) {\n            return this;\n        }\n        if (element.constructor == R.st.constructor) {\n            element = element[0];\n        }\n        element.node.parentNode.insertBefore(this.node, element.node);\n        R._insertbefore(this, element, this.paper);\n        return this;\n    };\n    elproto.blur = function (size) {\n        var s = this.node.runtimeStyle,\n            f = s.filter;\n        f = f.replace(blurregexp, E);\n        if (+size !== 0) {\n            this.attrs.blur = size;\n            s.filter = f + S + ms + \".Blur(pixelradius=\" + (+size || 1.5) + \")\";\n            s.margin = R.format(\"-{0}px 0 0 -{0}px\", round(+size || 1.5));\n        } else {\n            s.filter = f;\n            s.margin = 0;\n            delete this.attrs.blur;\n        }\n        return this;\n    };\n\n    R._engine.path = function (pathString, vml) {\n        var el = createNode(\"shape\");\n        el.style.cssText = cssDot;\n        el.coordsize = zoom + S + zoom;\n        el.coordorigin = vml.coordorigin;\n        var p = new Element(el, vml),\n            attr = {fill: \"none\", stroke: \"#000\"};\n        pathString && (attr.path = pathString);\n        p.type = \"path\";\n        p.path = [];\n        p.Path = E;\n        setFillAndStroke(p, attr);\n        vml.canvas && vml.canvas.appendChild(el);\n        var skew = createNode(\"skew\");\n        skew.on = true;\n        el.appendChild(skew);\n        p.skew = skew;\n        p.transform(E);\n        return p;\n    };\n    R._engine.rect = function (vml, x, y, w, h, r) {\n        var path = R._rectPath(x, y, w, h, r),\n            res = vml.path(path),\n            a = res.attrs;\n        res.X = a.x = x;\n        res.Y = a.y = y;\n        res.W = a.width = w;\n        res.H = a.height = h;\n        a.r = r;\n        a.path = path;\n        res.type = \"rect\";\n        return res;\n    };\n    R._engine.ellipse = function (vml, x, y, rx, ry) {\n        var res = vml.path(),\n            a = res.attrs;\n        res.X = x - rx;\n        res.Y = y - ry;\n        res.W = rx * 2;\n        res.H = ry * 2;\n        res.type = \"ellipse\";\n        setFillAndStroke(res, {\n            cx: x,\n            cy: y,\n            rx: rx,\n            ry: ry\n        });\n        return res;\n    };\n    R._engine.circle = function (vml, x, y, r) {\n        var res = vml.path(),\n            a = res.attrs;\n        res.X = x - r;\n        res.Y = y - r;\n        res.W = res.H = r * 2;\n        res.type = \"circle\";\n        setFillAndStroke(res, {\n            cx: x,\n            cy: y,\n            r: r\n        });\n        return res;\n    };\n    R._engine.image = function (vml, src, x, y, w, h) {\n        var path = R._rectPath(x, y, w, h),\n            res = vml.path(path).attr({stroke: \"none\"}),\n            a = res.attrs,\n            node = res.node,\n            fill = node.getElementsByTagName(fillString)[0];\n        a.src = src;\n        res.X = a.x = x;\n        res.Y = a.y = y;\n        res.W = a.width = w;\n        res.H = a.height = h;\n        a.path = path;\n        res.type = \"image\";\n        fill.parentNode == node && node.removeChild(fill);\n        fill.rotate = true;\n        fill.src = src;\n        fill.type = \"tile\";\n        res._.fillpos = [x, y];\n        res._.fillsize = [w, h];\n        node.appendChild(fill);\n        setCoords(res, 1, 1, 0, 0, 0);\n        return res;\n    };\n    R._engine.text = function (vml, x, y, text) {\n        var el = createNode(\"shape\"),\n            path = createNode(\"path\"),\n            o = createNode(\"textpath\");\n        x = x || 0;\n        y = y || 0;\n        text = text || \"\";\n        path.v = R.format(\"m{0},{1}l{2},{1}
57612\", round(x * zoom), round(y * zoom), round(x * zoom) + 1);\n        path.textpathok = true;\n        o.string = Str(text);\n        o.on = true;\n        el.style.cssText = cssDot;\n        el.coordsize = zoom + S + zoom;\n        el.coordorigin = \"0 0\";\n        var p = new Element(el, vml),\n            attr = {\n                fill: \"#000\",\n                stroke: \"none\",\n                font: R._availableAttrs.font,\n                text: text\n            };\n        p.shape = el;\n        p.path = path;\n        p.textpath = o;\n        p.type = \"text\";\n        p.attrs.text = Str(text);\n        p.attrs.x = x;\n        p.attrs.y = y;\n        p.attrs.w = 1;\n        p.attrs.h = 1;\n        setFillAndStroke(p, attr);\n        el.appendChild(o);\n        el.appendChild(path);\n        vml.canvas.appendChild(el);\n        var skew = createNode(\"skew\");\n        skew.on = true;\n        el.appendChild(skew);\n        p.skew = skew;\n        p.transform(E);\n        return p;\n    };\n    R._engine.setSize = function (width, height) {\n        var cs = this.canvas.style;\n        this.width = width;\n        this.height = height;\n        width == +width && (width += \"px\");\n        height == +height && (height += \"px\");\n        cs.width = width;\n        cs.height = height;\n        cs.clip = \"rect(0 \" + width + \" \" + height + \" 0)\";\n        if (this._viewBox) {\n            R._engine.setViewBox.apply(this, this._viewBox);\n        }\n        return this;\n    };\n    R._engine.setViewBox = function (x, y, w, h, fit) {\n        R.eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n        var paperSize = this.getSize(),\n            width = paperSize.width,\n            height = paperSize.height,\n            H, W;\n        if (fit) {\n            H = height / h;\n            W = width / w;\n            if (w * H < width) {\n                x -= (width - w * H) / 2 / H;\n            }\n            if (h * W < height) {\n                y -= (height - h * W) / 2 / W;\n            }\n        }\n        this._viewBox = [x, y, w, h, !!fit];\n        this._viewBoxShift = {\n            dx: -x,\n            dy: -y,\n            scale: paperSize\n        };\n        this.forEach(function (el) {\n            el.transform(\"...\");\n        });\n        return this;\n    };\n    var createNode;\n    R._engine.initWin = function (win) {\n            var doc = win.document;\n            if (doc.styleSheets.length < 31) {\n                doc.createStyleSheet().addRule(\".rvml\", \"behavior:url(#default#VML)\");\n            } else {\n                // no more room, add to the existing one\n                // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx\n                doc.styleSheets[0].addRule(\".rvml\", \"behavior:url(#default#VML)\");\n            }\n            try {\n                !doc.namespaces.rvml && doc.namespaces.add(\"rvml\", \"urn:schemas-microsoft-com:vml\");\n                createNode = function (tagName) {\n                    return doc.createElement('<rvml:' + tagName + ' class=\"rvml\">');\n                };\n            } catch (e) {\n                createNode = function (tagName) {\n                    return doc.createElement('<' + tagName + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">');\n                };\n            }\n        };\n    R._engine.initWin(R._g.win);\n    R._engine.create = function () {\n        var con = R._getContainer.apply(0, arguments),\n            container = con.container,\n            height = con.height,\n            s,\n            width = con.width,\n            x = con.x,\n            y = con.y;\n        if (!container) {\n            throw new Error(\"VML container not found.\");\n        }\n        var res = new R._Paper,\n            c = res.canvas = R._g.doc.createElement(\"div\"),\n            cs = c.style;\n        x = x || 0;\n        y = y || 0;\n        width = width || 512;\n        height = height || 342;\n        res.width = width;\n        res.height = height;\n        width == +width && (width += \"px\");\n        height == +height && (height += \"px\");\n        res.coordsize = zoom * 1e3 + S + zoom * 1e3;\n        res.coordorigin = \"0 0\";\n        res.span = R._g.doc.createElement(\"span\");\n        res.span.style.cssText = \"position:absolute;
57612left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\";\n        c.appendChild(res.span);\n        cs.cssText = R.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\", width, height);\n        if (container == 1) {\n            R._g.doc.body.appendChild(c);\n            cs.left = x + \"px\";\n            cs.top = y + \"px\";\n            cs.position = \"absolute\";\n        } else {\n            if (container.firstChild) {\n                container.insertBefore(c, container.firstChild);\n            } else {\n                container.appendChild(c);\n            }\n        }\n        res.renderfix = function () {};\n        return res;\n    };\n    R.prototype.clear = function () {\n        R.eve(\"raphael.clear\", this);\n        this.canvas.innerHTML = E;\n        this.span = R._g.doc.createElement(\"span\");\n        this.span.style.cssText = \"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\";\n        this.canvas.appendChild(this.span);\n        this.bottom = this.top = null;\n    };\n    R.prototype.remove = function () {\n        R.eve(\"raphael.remove\", this);\n        this.canvas.parentNode.removeChild(this.canvas);\n        for (var i in this) {\n            this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n        }\n        return true;\n    };\n\n    var setproto = R.st;\n    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n        setproto[method] = (function (methodname) {\n            return function () {\n                var arg = arguments;\n                return this.forEach(function (el) {\n                    el[methodname].apply(el, arg);\n                });\n            };\n        })(method);\n    }\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC52bWwuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SYXBoYWVsLy4vZGV2L3JhcGhhZWwudm1sLmpzP2JhZjAiXSwic291cmNlc0NvbnRlbnQiOlsiZGVmaW5lKFtcIi4vcmFwaGFlbC5jb3JlXCJdLCBmdW5jdGlvbihSKSB7XG4gICAgaWYgKFIgJiYgIVIudm1sKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaGFzID0gXCJoYXNPd25Qcm9wZXJ0eVwiLFxuICAgICAgICBTdHIgPSBTdHJpbmcsXG4gICAgICAgIHRvRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgICBtYXRoID0gTWF0aCxcbiAgICAgICAgcm91bmQgPSBtYXRoLnJvdW5kLFxuICAgICAgICBtbWF4ID0gbWF0aC5tYXgsXG4gICAgICAgIG1taW4gPSBtYXRoLm1pbixcbiAgICAgICAgYWJzID0gbWF0aC5hYnMsXG4gICAgICAgIGZpbGxTdHJpbmcgPSBcImZpbGxcIixcbiAgICAgICAgc2VwYXJhdG9yID0gL1ssIF0rLyxcbiAgICAgICAgZXZlID0gUi5ldmUsXG4gICAgICAgIG1zID0gXCIgcHJvZ2lkOkRYSW1hZ2VUcmFuc2Zvcm0uTWljcm9zb2Z0XCIsXG4gICAgICAgIFMgPSBcIiBcIixcbiAgICAgICAgRSA9IFwiXCIsXG4gICAgICAgIG1hcCA9IHtNOiBcIm1cIiwgTDogXCJsXCIsIEM6IFwiY1wiLCBaOiBcInhcIiwgbTogXCJ0XCIsIGw6IFwiclwiLCBjOiBcInZcIiwgejogXCJ4XCJ9LFxuICAgICAgICBiaXRlcyA9IC8oW2NsbXpdKSw/KFteY2xtel0qKS9naSxcbiAgICAgICAgYmx1cnJlZ2V4cCA9IC8gcHJvZ2lkOlxcUytCbHVyXFwoW15cXCldK1xcKS9nLFxuICAgICAgICB2YWwgPSAvLT9bXixcXHMtXSsvZyxcbiAgICAgICAgY3NzRG90ID0gXCJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0OjA7dG9wOjA7d2lkdGg6MXB4O2hlaWdodDoxcHg7YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTClcIixcbiAgICAgICAgem9vbSA9IDIxNjAwLFxuICAgICAgICBwYXRoVHlwZXMgPSB7cGF0aDogMSwgcmVjdDogMSwgaW1hZ2U6IDF9LFxuICAgICAgICBvdmFsVHlwZXMgPSB7Y2lyY2xlOiAxLCBlbGxpcHNlOiAxfSxcbiAgICAgICAgcGF0aDJ2bWwgPSBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAgICAgdmFyIHRvdGFsID0gIC9bYWhxc3R2XS9pZyxcbiAgICAgICAgICAgICAgICBjb21tYW5kID0gUi5fcGF0aFRvQWJzb2x1dGU7XG4gICAgICAgICAgICBTdHIocGF0aCkubWF0Y2godG90YWwpICYmIChjb21tYW5kID0gUi5fcGF0aDJjdXJ2ZSk7XG4gICAgICAgICAgICB0b3RhbCA9IC9bY2xtel0vZztcbiAgICAgICAgICAgIGlmIChjb21tYW5kID09IFIuX3BhdGhUb0Fic29sdXRlICYmICFTdHIocGF0aCkubWF0Y2godG90YWwpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFN0cihwYXRoKS5yZXBsYWNlKGJpdGVzLCBmdW5jdGlvbiAoYWxsLCBjb21tYW5kLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWxzID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBpc01vdmUgPSBjb21tYW5kLnRvTG93ZXJDYXNlKCkgPT0gXCJtXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXMgPSBtYXBbY29tbWFuZF07XG4gICAgICAgICAgICAgICAgICAgIGFyZ3MucmVwbGFjZSh2YWwsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTW92ZSAmJi
57612B2YWxzLmxlbmd0aCA9PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzICs9IHZhbHMgKyBtYXBbY29tbWFuZCA9PSBcIm1cIiA/IFwibFwiIDogXCJMXCJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHMucHVzaChyb3VuZCh2YWx1ZSAqIHpvb20pKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXMgKyB2YWxzO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcGEgPSBjb21tYW5kKHBhdGgpLCBwLCByO1xuICAgICAgICAgICAgcmVzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBwYS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcCA9IHBhW2ldO1xuICAgICAgICAgICAgICAgIHIgPSBwYVtpXVswXS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHIgPT0gXCJ6XCIgJiYgKHIgPSBcInhcIik7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDEsIGpqID0gcC5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHIgKz0gcm91bmQocFtqXSAqIHpvb20pICsgKGogIT0gamogLSAxID8gXCIsXCIgOiBFKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzLnB1c2gocik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzLmpvaW4oUyk7XG4gICAgICAgIH0sXG4gICAgICAgIGNvbXBlbnNhdGlvbiA9IGZ1bmN0aW9uIChkZWcsIGR4LCBkeSkge1xuICAgICAgICAgICAgdmFyIG0gPSBSLm1hdHJpeCgpO1xuICAgICAgICAgICAgbS5yb3RhdGUoLWRlZywgLjUsIC41KTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZHg6IG0ueChkeCwgZHkpLFxuICAgICAgICAgICAgICAgIGR5OiBtLnkoZHgsIGR5KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0Q29vcmRzID0gZnVuY3Rpb24gKHAsIHN4LCBzeSwgZHgsIGR5LCBkZWcpIHtcbiAgICAgICAgICAgIHZhciBfID0gcC5fLFxuICAgICAgICAgICAgICAgIG0gPSBwLm1hdHJpeCxcbiAgICAgICAgICAgICAgICBmaWxscG9zID0gXy5maWxscG9zLFxuICAgICAgICAgICAgICAgIG8gPSBwLm5vZGUsXG4gICAgICAgICAgICAgICAgcyA9IG8uc3R5bGUsXG4gICAgICAgICAgICAgICAgeSA9IDEsXG4gICAgICAgICAgICAgICAgZmxpcCA9IFwiXCIsXG4gICAgICAgICAgICAgICAgZHhkeSxcbiAgICAgICAgICAgICAgICBreCA9IHpvb20gLyBzeCxcbiAgICAgICAgICAgICAgICBreSA9IHpvb20gLyBzeTtcbiAgICAgICAgICAgIHMudmlzaWJpbGl0eSA9IFwiaGlkZGVuXCI7XG4gICAgICAgICAgICBpZiAoIXN4IHx8ICFzeSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG8uY29vcmRzaXplID0gYWJzKGt4KSArIFMgKyBhYnMoa3kpO1xuICAgICAgICAgICAgcy5yb3RhdGlvbiA9IGRlZyAqIChzeCAqIHN5IDwgMCA/IC0xIDogMSk7XG4gICAgICAgICAgICBpZiAoZGVnKSB7XG4gICAgICAgICAgICAgICAgdmFyIGMgPSBjb21wZW5zYXRpb24oZGVnLCBkeCwgZHkpO1xuICAgICAgICAgICAgICAgIGR4ID0gYy5keDtcbiAgICAgICAgICAgICAgICBkeSA9IGMuZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzeCA8IDAgJiYgKGZsaXAgKz0gXCJ4XCIpO1xuICAgICAgICAgICAgc3kgPCAwICYmIChmbGlwICs9IFwiIHlcIikgJiYgKHkgPSAtMSk7XG4gICAgICAgICAgICBzLmZsaXAgPSBmbGlwO1xuICAgICAgICAgICAgby5jb29yZG9yaWdpbiA9IChkeCAqIC1reCkgKyBTICsgKGR5ICogLWt5KTtcbiAgICAgICAgICAgIGlmIChmaWxscG9zIHx8IF8uZmlsbHNpemUpIHtcbiAgICAgICAgICAgICAgICB2Y
57612XIgZmlsbCA9IG8uZ2V0RWxlbWVudHNCeVRhZ05hbWUoZmlsbFN0cmluZyk7XG4gICAgICAgICAgICAgICAgZmlsbCA9IGZpbGwgJiYgZmlsbFswXTtcbiAgICAgICAgICAgICAgICBvLnJlbW92ZUNoaWxkKGZpbGwpO1xuICAgICAgICAgICAgICAgIGlmIChmaWxscG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIGMgPSBjb21wZW5zYXRpb24oZGVnLCBtLngoZmlsbHBvc1swXSwgZmlsbHBvc1sxXSksIG0ueShmaWxscG9zWzBdLCBmaWxscG9zWzFdKSk7XG4gICAgICAgICAgICAgICAgICAgIGZpbGwucG9zaXRpb24gPSBjLmR4ICogeSArIFMgKyBjLmR5ICogeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF8uZmlsbHNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbC5zaXplID0gXy5maWxsc2l6ZVswXSAqIGFicyhzeCkgKyBTICsgXy5maWxsc2l6ZVsxXSAqIGFicyhzeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG8uYXBwZW5kQ2hpbGQoZmlsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzLnZpc2liaWxpdHkgPSBcInZpc2libGVcIjtcbiAgICAgICAgfTtcbiAgICBSLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gIFwiWW91ciBicm93c2VyIGRvZXNuXFx1MjAxOXQgc3VwcG9ydCBTVkcuIEZhbGxpbmcgZG93biB0byBWTUwuXFxuWW91IGFyZSBydW5uaW5nIFJhcGhhXFx4ZWJsIFwiICsgdGhpcy52ZXJzaW9uO1xuICAgIH07XG4gICAgdmFyIGFkZEFycm93ID0gZnVuY3Rpb24gKG8sIHZhbHVlLCBpc0VuZCkge1xuICAgICAgICB2Y
57612XIgdmFsdWVzID0gU3RyKHZhbHVlKS50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiLVwiKSxcbiAgICAgICAgICAgIHNlID0gaXNFbmQgPyBcImVuZFwiIDogXCJzdGFydFwiLFxuICAgICAgICAgICAgaSA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgICB0eXBlID0gXCJjbGFzc2ljXCIsXG4gICAgICAgICAgICB3ID0gXCJtZWRpdW1cIixcbiAgICAgICAgICAgIGggPSBcIm1lZGl1bVwiO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHZhbHVlc1tpXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgXCJibG9ja1wiOlxuICAgICAgICAgICAgICAgIGNhc2UgXCJjbGFzc2ljXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcIm92YWxcIjpcbiAgICAgICAgICAgICAgICBjYXNlIFwiZGlhbW9uZFwiOlxuICAgICAgICAgICAgICAgIGNhc2UgXCJvcGVuXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcIm5vbmVcIjpcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcIndpZGVcIjpcbiAgICAgICAgICAgICAgICBjYXNlIFwibmFycm93XCI6IGggPSB2YWx1ZXNbaV07IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJsb25nXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcInNob3J0XCI6IHcgPSB2YWx1ZXNbaV07IGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBzdHJva2UgPSBvLm5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdHJva2VcIilbMF07XG4gICAgICAgIHN0cm9rZVtzZSArIFwiYXJyb3dcIl0gPSB0eXBlO1xuICAgICAgICBzdHJva2Vbc2UgKyBcImFycm93bGVuZ3RoXCJdID0gdztcbiAgICAgICAgc3Ryb2tlW3NlICsgXCJhcnJvd3dpZHRoXCJdID0gaDtcbiAgICB9LFxuICAgIHNldEZpbGxBbmRTdHJva2UgPSBmdW5jdGlvbiAobywgcGFyYW1zKSB7XG4gICAgICAgIC8vIG8ucGFwZXIuY2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgby5hdHRycyA9IG8uYXR0cnMgfHwge307XG4gICAgICAgIHZhciBub2RlID0gby5ub2RlLFxuICAgICAgICAgICAgYSA9IG8uYXR0cnMsXG4gICAgICAgICAgICBzID0gbm9kZS5zdHlsZSxcbiAgICAgICAgICAgIHh5LFxuICAgICAgICAgICAgbmV3cGF0aCA9IHBhdGhUeXBlc1tvLnR5cGVdICYmIChwYXJhbXMueCAhPSBhLnggfHwgcGFyYW1zLnkgIT0gYS55IHx8IHBhcmFtcy53aWR0aCAhPSBhLndpZHRoIHx8IHBhcmFtcy5oZWlnaHQgIT0gYS5oZWlnaHQgfHwgcGFyYW1zLmN4ICE9IGEuY3ggfHwgcGFyYW1zLmN5ICE9IGEuY3kgfHwgcGFyYW1zLnJ4ICE9IGEucnggfHwgcGFyYW1zLnJ5ICE9IGEucnkgfHwgcGFyYW1zLnIgIT0gYS5yKSxcbiAgICAgICAgICAgIGlzT3ZhbCA9IG92YWxUeXBlc1tvLnR5cGVdICYmIChhLmN4ICE9IHBhcmFtcy5jeCB8fCBhLmN5ICE9IHBhcmFtcy5jeSB8fCBhLnIgIT0gcGFyYW1zLnIgfHwgYS5yeCAhPSBwYXJhbXMucnggfHwgYS5yeSAhPSBwYXJhbXMucnkpLFxuICAgICAgICAgICAgcmVzID0gbztcblxuXG4gICAgICAgIGZvciAodmFyIHBhciBpbiBwYXJhbXMpIGlmIChwYXJhbXNbaGFzXShwYXIpKSB7XG4gICAgICAgICAgICBhW3Bhcl0gPSBwYXJhbXNbcGFyXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV3cGF0aCkge1xuICAgICAgICAgICAgYS5wYXRoID0gUi5fZ2V0UGF0aFtvLnR5cGVdKG8pO1xuICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgfVxuICAgICAgICBwYXJhbXMuaHJlZiAmJiAobm9kZS5ocmVmID0gcGFyYW1zLmhyZWYpO1xuICAgICAgICBwYXJhbXMudGl0bGUgJiYgKG5vZGUudGl0bGUgPSBwYXJhbXMudGl0bGUpO1xuICAgICAgICBwYXJhbXMudGFyZ2V0ICYmIChub2RlLnRhcmdldCA9IHBhcmFtcy50YXJnZXQpO1xuICAgICAgICBwYXJhbXMuY3Vyc29yICYmIChzLmN1cnNvciA9IHBhcmFtcy5jdXJzb3IpO1xuICAgICAgICBcImJsdXJcIiBpbiBwYXJhbXMgJiYgby5ibHVyKHBhcmFtcy5ibHVyKTtcbiAgICAgICAgaWYgKHBhcmFtcy5wYXRoICYmIG8udHlwZSA9PSBcInBhdGhcIiB8fCBuZXdwYXRoKSB7XG4gICAgICAgICAgICBub2RlLnBhdGggPSBwYXRoMnZtbCh+U3RyKGEucGF0aCkudG9Mb3dlckNhc2UoKS5pbmRleE9mKFwiclwiKSA/IFIuX3BhdGhUb0Fic29sdXRlKGEucGF0aCkgOiBhLnBhdGgpO1xuICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgIGlmIChvLnR5cGUgPT0gXCJpbWFnZVwiKSB7XG4gICAgICAgICAgICAgICAgby5fLmZpbGxwb3MgPSBbYS54LCBhLnldO1xuICAgICAgICAgICAgICAgIG8uXy5maWxsc2l6ZSA9IFthLndpZHRoLCBhLmhlaWdodF07XG4gICAgICAgICAgICAgICAgc2V0Q29vcmRzKG8sIDEsIDEsIDAsIDAsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFwidHJhbnNmb3JtXCIgaW4gcGFyYW1zICYmIG8udHJhbnNmb3JtKHBhcmFtcy50cmFuc2Zvcm0pO1xuICAgICAgICBpZiAoaXNPdmFsKSB7XG4gICAgICAgICAgICB2Y
57612XIgY3ggPSArYS5jeCxcbiAgICAgICAgICAgICAgICBjeSA9ICthLmN5LFxuICAgICAgICAgICAgICAgIHJ4ID0gK2EucnggfHwgK2EuciB8fCAwLFxuICAgICAgICAgICAgICAgIHJ5ID0gK2EucnkgfHwgK2EuciB8fCAwO1xuICAgICAgICAgICAgbm9kZS5wYXRoID0gUi5mb3JtYXQoXCJhcnswfSx7MX0sezJ9LHszfSx7NH0sezF9LHs0fSx7MX14XCIsIHJvdW5kKChjeCAtIHJ4KSAqIHpvb20pLCByb3VuZCgoY3kgLSByeSkgKiB6b29tKSwgcm91bmQoKGN4ICsgcngpICogem9vbSksIHJvdW5kKChjeSArIHJ5KSAqIHpvb20pLCByb3VuZChjeCAqIHpvb20pKTtcbiAgICAgICAgICAgIG8uXy5kaXJ0eSA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFwiY2xpcC1yZWN0XCIgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgcmVjdCA9IFN0cihwYXJhbXNbXCJjbGlwLXJlY3RcIl0pLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgICAgICBpZiAocmVjdC5sZW5ndGggPT0gNCkge1xuICAgICAgICAgICAgICAgIHJlY3RbMl0gPSArcmVjdFsyXSArICgrcmVjdFswXSk7XG4gICAgICAgICAgICAgICAgcmVjdFszXSA9ICtyZWN0WzNdICsgKCtyZWN0WzFdKTtcbiAgICAgICAgICAgICAgICB2YXIgZGl2ID0gbm9kZS5jbGlwUmVjdCB8fCBSLl9nLmRvYy5jcmVhdGVFbGVtZW50KFwiZGl2XCIpLFxuICAgICAgICAgICAgICAgICAgICBkc3R5bGUgPSBkaXYuc3R5bGU7XG4gICAgICAgICAgICAgICAgZHN0eWxlLmNsaXAgPSBSLmZvcm1hdChcInJlY3QoezF9cHggezJ9cHggezN9cHggezB9cHgpXCIsIHJlY3QpO1xuICAgICAgICAgICAgICAgIGlmICghbm9kZS5jbGlwUmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBkc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgICAgICAgICAgICAgIGRzdHlsZS50b3AgPSAwO1xuICAgICAgICAgICAgICAgICAgICBkc3R5bGUubGVmdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGRzdHlsZS53aWR0aCA9IG8ucGFwZXIud2lkdGggKyBcInB4XCI7XG4gICAgICAgICAgICAgICAgICAgIGRzdHlsZS5oZWlnaHQgPSBvLnBhcGVyLmhlaWdodCArIFwicHhcIjtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShkaXYsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBkaXYuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2xpcFJlY3QgPSBkaXY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFwYXJhbXNbXCJjbGlwLXJlY3RcIl0pIHtcbiAgICAgICAgICAgICAgICBub2RlLmNsaXBSZWN0ICYmIChub2RlLmNsaXBSZWN0LnN0eWxlLmNsaXAgPSBcImF1dG9cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG8udGV4dHBhdGgpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0cGF0aFN0eWxlID0gby50ZXh0cGF0aC5zdHlsZTtcbiAgICAgICAgICAgIHBhcmFtcy5mb250ICYmICh0ZXh0cGF0aFN0eWxlLmZvbnQgPSBwYXJhbXMuZm9udCk7XG4gICAgICAgICAgICBwYXJhbXNbXCJmb250LWZhbWlseVwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250RmFtaWx5ID0gJ1wiJyArIHBhcmFtc1tcImZvbnQtZmFtaWx5XCJdLnNwbGl0KFwiLFwiKVswXS5yZXBsYWNlKC9eWydcIl0rfFsnXCJdKyQvZywgRSkgKyAnXCInKTtcbiAgICAgICAgICAgIHBhcmFtc1tcImZvbnQtc2l6ZVwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250U2l6ZSA9IHBhcmFtc1tcImZvbnQtc2l6ZVwiXSk7XG4gICAgICAgICAgICBwYXJhbXNbXCJmb250LXdlaWdodFwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250V2VpZ2h0ID0gcGFyYW1zW1wiZm9udC13ZWlnaHRcIl0pO1xuICAgICAgICAgICAgcGFyYW1zW1wiZm9udC1zdHlsZVwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250U3R5bGUgPSBwYXJhbXNbXCJmb250LXN0eWxlXCJdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXCJhcnJvdy1zdGFydFwiIGluIHBhcmFtcykge1xuICAgICAgICAgICAgYWRkQXJyb3cocmVzLCBwYXJhbXNbXCJhcnJvdy1zdGFydFwiXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFwiYXJyb3ctZW5kXCIgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBhZGRBcnJvdyhyZXMsIHBhcmFtc1tcImFycm93LWVuZFwiXSwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy5vcGFjaXR5ICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtcy5maWxsICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtcy5zcmMgIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zLnN0cm9rZSAhPSBudWxsIHx8XG4gICAgICAgICAgICBwYXJhbXNbXCJzdHJva2Utd2lkdGhcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLW9wYWNpdHlcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wiZmlsbC1vcGFjaXR5XCJdICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1kYXNoYXJyYXlcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLW1pdGVybGltaXRcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLWxpbmVqb2luXCJdICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBmaWxsID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZShmaWxsU3RyaW5nKSxcbiAgICAgICAgICAgICAgICBuZXdmaWxsID0gZmFsc2U7XG4gICAgICAgICAgICBmaWxsID0gZmlsbCAmJiBmaWxsWzBdO1xuICAgICAgICAgICAgIWZpbGwgJiYgKG5ld2ZpbGwgPSBmaWxsID0gY3JlYXRlTm9kZShmaWxsU3RyaW5nKSk7XG4gICAgICAgICAgICBpZiAoby50eXBlID09IFwiaW1hZ2VcIiAmJiBwYXJhbXMuc3JjKSB7XG4gICAgICAgICAgICAgICAgZmlsbC5zcmMgPSBwYXJhbXMuc3JjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyYW1zLmZpbGwgJiYgKGZpbGwub24gPSB0cnVlKTtcbiAgICAgICAgICAgIGlmIChmaWxsLm9uID09IG51bGwgfHwgcGFyYW1zLmZpbGwgPT0gXCJub25lXCIgfHwgcGFyYW1zLmZpbGwgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmaWxsLm9uID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlsbC5vbiAmJiBwYXJhbXMuZmlsbCkge1xuICAgICAgICAgICAgICAgI
57612HZhciBpc1VSTCA9IFN0cihwYXJhbXMuZmlsbCkubWF0Y2goUi5fSVNVUkwpO1xuICAgICAgICAgICAgICAgIGlmIChpc1VSTCkge1xuICAgICAgICAgICAgICAgICAgICBmaWxsLnBhcmVudE5vZGUgPT0gbm9kZSAmJiBub2RlLnJlbW92ZUNoaWxkKGZpbGwpO1xuICAgICAgICAgICAgICAgICAgICBmaWxsLnJvdGF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGZpbGwuc3JjID0gaXNVUkxbMV07XG4gICAgICAgICAgICAgICAgICAgIGZpbGwudHlwZSA9IFwidGlsZVwiO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYmJveCA9IG8uZ2V0QkJveCgxKTtcbiAgICAgICAgICAgICAgICAgICAgZmlsbC5wb3NpdGlvbiA9IGJib3gueCArIFMgKyBiYm94Lnk7XG4gICAgICAgICAgICAgICAgICAgIG8uXy5maWxscG9zID0gW2Jib3gueCwgYmJveC55XTtcblxuICAgICAgICAgICAgICAgICAgICBSLl9wcmVsb2FkKGlzVVJMWzFdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvLl8uZmlsbHNpemUgPSBbdGhpcy5vZmZzZXRXaWR0aCwgdGhpcy5vZmZzZXRIZWlnaHRdO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmaWxsLmNvbG9yID0gUi5nZXRSR0IocGFyYW1zLmZpbGwpLmhleDtcbiAgICAgICAgICAgICAgICAgICAgZmlsbC5zcmMgPSBFO1xuICAgICAgICAgICAgICAgICAgICBmaWxsLnR5cGUgPSBcInNvbGlkXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChSLmdldFJHQihwYXJhbXMuZmlsbCkuZXJyb3IgJiYgKHJlcy50eXBlIGluIHtjaXJjbGU6IDEsIGVsbGlwc2U6IDF9IHx8IFN0cihwYXJhbXMuZmlsbCkuY2hhckF0KCkgIT0gXCJyXCIpICYmIGFkZEdyYWRpZW50RmlsbChyZXMsIHBhcmFtcy5maWxsLCBmaWxsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYS5maWxsID0gXCJub25lXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBhLmdyYWRpZW50ID0gcGFyYW1zLmZpbGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsLnJvdGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFwiZmlsbC1vcGFjaXR5XCIgaW4gcGFyYW1zIHx8IFwib3BhY2l0eVwiIGluIHBhcmFtcykge1xuICAgICAgICAgICAgICAgIHZhciBvcGFjaXR5ID0gKCgrYVtcImZpbGwtb3BhY2l0eVwiXSArIDEgfHwgMikgLSAxKSAqICgoK2Eub3BhY2l0eSArIDEgfHwgMikgLSAxKSAqICgoK1IuZ2V0UkdCKHBhcmFtcy5maWxsKS5vICsgMSB8fCAyKSAtIDEpO1xuICAgICAgICAgICAgICAgIG9wYWNpdHkgPSBtbWluKG1tYXgob3BhY2l0eSwgMCksIDEpO1xuICAgICAgICAgICAgICAgIGZpbGwub3BhY2l0eSA9IG9wYWNpdHk7XG4gICAgICAgICAgICAgICAgaWYgKGZpbGwuc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGwuY29sb3IgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGZpbGwpO1xuICAgICAgICAgICAgdmFyIHN0cm9rZSA9IChub2RlLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwic3Ryb2tlXCIpICYmIG5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdHJva2VcIilbMF0pLFxuICAgICAgICAgICAgbmV3c3Ryb2tlID0gZmFsc2U7XG4gICAgICAgICAgICAhc3Ryb2tlICYmIChuZXdzdHJva2UgPSBzdHJva2UgPSBjcmVhdGVOb2RlKFwic3Ryb2tlXCIpKTtcbiAgICAgICAgICAgIGlmICgocGFyYW1zLnN0cm9rZSAmJiBwYXJhbXMuc3Ryb2tlICE9IFwibm9uZVwiKSB8fFxuICAgICAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS13aWR0aFwiXSB8fFxuICAgICAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1vcGFjaXR5XCJdICE9IG51bGwgfHxcbiAgICAgICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtZGFzaGFycmF5XCJdIHx8XG4gICAgICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLW1pdGVybGltaXRcIl0gfHxcbiAgICAgICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtbGluZWpvaW5cIl0gfHxcbiAgICAgICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtbGluZWNhcFwiXSkge1xuICAgICAgICAgICAgICAgIHN0cm9rZS5vbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAocGFyYW1zLnN0cm9rZSA9PSBcIm5vbmVcIiB8fCBwYXJhbXMuc3Ryb2tlID09PSBudWxsIHx8IHN0cm9rZS5vbiA9PSBudWxsIHx8IHBhcmFtcy5zdHJva2UgPT0gMCB8fCBwYXJhbXNbXCJzdHJva2Utd2lkdGhcIl0gPT0gMCkgJiYgKHN0cm9rZS5vbiA9IGZhbHNlKTtcbiAgICAgICAgICAgIHZhciBzdHJva2VDb2xvciA9IFIuZ2V0UkdCKHBhcmFtcy5zdHJva2UpO1xuICAgICAgICAgICAgc3Ryb2tlLm9uICYmIHBhcmFtcy5zdHJva2UgJiYgKHN0cm9rZS5jb2xvciA9IHN0cm9rZUNvbG9yLmhleCk7XG4gICAgICAgICAgICBvcGFjaXR5ID0gKCgrYVtcInN0cm9rZS1vcGFjaXR5XCJdICsgMSB8fCAyKSAtIDEpICogKCgrYS5vcGFjaXR5ICsgMSB8fCAyKSAtIDEpICogKCgrc3Ryb2tlQ29sb3IubyArIDEgfHwgMikgLSAxKTtcbiAgICAgICAgICAgIHZhciB3aWR0aCA9ICh0b0Zsb2F0KHBhcmFtc1tcInN0cm9rZS13aWR0aFwiXSkgfHwgMSkgKiAuNzU7XG4gICAgICAgICAgICBvcGFjaXR5ID0gbW1pbihtbWF4KG9wYWNpdHksIDApLCAxKTtcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS13aWR0aFwiXSA9PSBudWxsICYmICh3aWR0aCA9IGFbXCJzdHJva2Utd2lkdGhcIl0pO1xuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLXdpZHRoXCJdICYmIChzdHJva2Uud2VpZ2h0ID0gd2lkdGgpO1xuICAgICAgICAgICAgd2lkdGggJiYgd2lkdGggPCAxICYmIChvcGFjaXR5ICo9IHdpZHRoKSAmJiAoc3Ryb2tlLndlaWdodCA9IDEpO1xuICAgICAgICAgICAgc3Ryb2tlLm9wYWNpdHkgPSBvcGFjaXR5O1xuXG4gICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtbGluZWpvaW5cIl0gJiYgKHN0cm9rZS5qb2luc3R5bGUgPSBwYXJhbXNbXCJzdHJva2UtbGluZWpvaW5cIl0gfHwgXCJtaXRlclwiKTtcbiAgICAgICAgICAgI
57612HN0cm9rZS5taXRlcmxpbWl0ID0gcGFyYW1zW1wic3Ryb2tlLW1pdGVybGltaXRcIl0gfHwgODtcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdICYmIChzdHJva2UuZW5kY2FwID0gcGFyYW1zW1wic3Ryb2tlLWxpbmVjYXBcIl0gPT0gXCJidXR0XCIgPyBcImZsYXRcIiA6IHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdID09IFwic3F1YXJlXCIgPyBcInNxdWFyZVwiIDogXCJyb3VuZFwiKTtcbiAgICAgICAgICAgIGlmIChcInN0cm9rZS1kYXNoYXJyYXlcIiBpbiBwYXJhbXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGFzaGFycmF5ID0ge1xuICAgICAgICAgICAgICAgICAgICBcIi1cIjogXCJzaG9ydGRhc2hcIixcbiAgICAgICAgICAgICAgICAgICAgXCIuXCI6IFwic2hvcnRkb3RcIixcbiAgICAgICAgICAgICAgICAgICAgXCItLlwiOiBcInNob3J0ZGFzaGRvdFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi0uLlwiOiBcInNob3J0ZGFzaGRvdGRvdFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi4gXCI6IFwiZG90XCIsXG4gICAgICAgICAgICAgICAgICAgIFwiLSBcIjogXCJkYXNoXCIsXG4gICAgICAgICAgICAgICAgICAgIFwiLS1cIjogXCJsb25nZGFzaFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi0gLlwiOiBcImRhc2hkb3RcIixcbiAgICAgICAgICAgICAgICAgICAgXCItLS5cIjogXCJsb25nZGFzaGRvdFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi0tLi5cIjogXCJsb25nZGFzaGRvdGRvdFwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBzdHJva2UuZGFzaHN0eWxlID0gZGFzaGFycmF5W2hhc10ocGFyYW1zW1wic3Ryb2tlLWRhc2hhcnJheVwiXSkgPyBkYXNoYXJyYXlbcGFyYW1zW1wic3Ryb2tlLWRhc2hhcnJheVwiXV0gOiBFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3c3Ryb2tlICYmIG5vZGUuYXBwZW5kQ2hpbGQoc3Ryb2tlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzLnR5cGUgPT0gXCJ0ZXh0XCIpIHtcbiAgICAgICAgICAgIHJlcy5wYXBlci5jYW52YXMuc3R5bGUuZGlzcGxheSA9IEU7XG4gICAgICAgICAgICB2Y
57612XIgc3BhbiA9IHJlcy5wYXBlci5zcGFuLFxuICAgICAgICAgICAgICAgIG0gPSAxMDAsXG4gICAgICAgICAgICAgICAgZm9udFNpemUgPSBhLmZvbnQgJiYgYS5mb250Lm1hdGNoKC9cXGQrKD86XFwuXFxkKik/KD89cHgpLyk7XG4gICAgICAgICAgICBzID0gc3Bhbi5zdHlsZTtcbiAgICAgICAgICAgIGEuZm9udCAmJiAocy5mb250ID0gYS5mb250KTtcbiAgICAgICAgICAgIGFbXCJmb250LWZhbWlseVwiXSAmJiAocy5mb250RmFtaWx5ID0gYVtcImZvbnQtZmFtaWx5XCJdKTtcbiAgICAgICAgICAgIGFbXCJmb250LXdlaWdodFwiXSAmJiAocy5mb250V2VpZ2h0ID0gYVtcImZvbnQtd2VpZ2h0XCJdKTtcbiAgICAgICAgICAgIGFbXCJmb250LXN0eWxlXCJdICYmIChzLmZvbnRTdHlsZSA9IGFbXCJmb250LXN0eWxlXCJdKTtcbiAgICAgICAgICAgIGZvbnRTaXplID0gdG9GbG9hdChhW1wiZm9udC1zaXplXCJdIHx8IGZvbnRTaXplICYmIGZvbnRTaXplWzBdKSB8fCAxMDtcbiAgICAgICAgICAgIHMuZm9udFNpemUgPSBmb250U2l6ZSAqIG0gKyBcInB4XCI7XG4gICAgICAgICAgICByZXMudGV4dHBhdGguc3RyaW5nICYmIChzcGFuLmlubmVySFRNTCA9IFN0cihyZXMudGV4dHBhdGguc3RyaW5nKS5yZXBsYWNlKC88L2csIFwiJiM2MDtcIikucmVwbGFjZSgvJi9nLCBcIiYjMzg7XCIpLnJlcGxhY2UoL1xcbi9nLCBcIjxicj5cIikpO1xuICAgICAgICAgICAgdmFyIGJyZWN0ID0gc3Bhbi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHJlcy5XID0gYS53ID0gKGJyZWN0LnJpZ2h0IC0gYnJlY3QubGVmdCkgLyBtO1xuICAgICAgICAgICAgcmVzLkggPSBhLmggPSAoYnJlY3QuYm90dG9tIC0gYnJlY3QudG9wKSAvIG07XG4gICAgICAgICAgICAvLyByZXMucGFwZXIuY2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgIHJlcy5YID0gYS54O1xuICAgICAgICAgICAgcmVzLlkgPSBhLnkgKyByZXMuSCAvIDI7XG5cbiAgICAgICAgICAgIChcInhcIiBpbiBwYXJhbXMgfHwgXCJ5XCIgaW4gcGFyYW1zKSAmJiAocmVzLnBhdGgudiA9IFIuZm9ybWF0KFwibXswfSx7MX1sezJ9LHsxfVwiLCByb3VuZChhLnggKiB6b29tKSwgcm91bmQoYS55ICogem9vbSksIHJvdW5kKGEueCAqIHpvb20pICsgMSkpO1xuICAgICAgICAgICAgdmFyIGRpcnR5YXR0cnMgPSBbXCJ4XCIsIFwieVwiLCBcInRleHRcIiwgXCJmb250XCIsIFwiZm9udC1mYW1pbHlcIiwgXCJmb250LXdlaWdodFwiLCBcImZvbnQtc3R5bGVcIiwgXCJmb250LXNpemVcIl07XG4gICAgICAgICAgICBmb3IgKHZhciBkID0gMCwgZGQgPSBkaXJ0eWF0dHJzLmxlbmd0aDsgZCA8IGRkOyBkKyspIGlmIChkaXJ0eWF0dHJzW2RdIGluIHBhcmFtcykge1xuICAgICAgICAgICAgICAgIHJlcy5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGV4dC1hbmNob3IgZW11bGF0aW9uXG4gICAgICAgICAgICBzd2l0Y2ggKGFbXCJ0ZXh0LWFuY2hvclwiXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgXCJzdGFydFwiOlxuICAgICAgICAgICAgICAgICAgICByZXMudGV4dHBhdGguc3R5bGVbXCJ2LXRleHQtYWxpZ25cIl0gPSBcImxlZnRcIjtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmJieCA9IHJlcy5XIC8gMjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgICAgICAgICAgIHJlcy50ZXh0cGF0aC5zdHlsZVtcInYtdGV4dC1hbGlnblwiXSA9IFwicmlnaHRcIjtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmJieCA9IC1yZXMuVyAvIDI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVzLnRleHRwYXRoLnN0eWxlW1widi10ZXh0LWFsaWduXCJdID0gXCJjZW50ZXJcIjtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmJieCA9IDA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMudGV4dHBhdGguc3R5bGVbXCJ2LXRleHQta2VyblwiXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzLnBhcGVyLmNhbnZhcy5zdHlsZS5kaXNwbGF5ID0gRTtcbiAgICB9LFxuICAgIGFkZEdyYWRpZW50RmlsbCA9IGZ1bmN0aW9uIChvLCBncmFkaWVudCwgZmlsbCkge1xuICAgICAgICBvLmF0dHJzID0gby5hdHRycyB8fCB7fTtcbiAgICAgICAgdmFyIGF0dHJzID0gby5hdHRycyxcbiAgICAgICAgICAgIHBvdyA9IE1hdGgucG93LFxuICAgICAgICAgICAgb3BhY2l0eSxcbiAgICAgICAgICAgIG9pbmRleCxcbiAgICAgICAgICAgIHR5cGUgPSBcImxpbmVhclwiLFxuICAgICAgICAgICAgZnhmeSA9IFwiLjUgLjVcIjtcbiAgICAgICAgby5hdHRycy5ncmFkaWVudCA9IGdyYWRpZW50O1xuICAgICAgICBncmFkaWVudCA9IFN0cihncmFkaWVudCkucmVwbGFjZShSLl9yYWRpYWxfZ3JhZGllbnQsIGZ1bmN0aW9uIChhbGwsIGZ4LCBmeSkge1xuICAgICAgICAgICAgdHlwZSA9IFwicmFkaWFsXCI7XG4gICAgICAgICAgICBpZiAoZnggJiYgZnkpIHtcbiAgICAgICAgICAgICAgICBmeCA9IHRvRmxvYXQoZngpO1xuICAgICAgICAgICAgICAgIGZ5ID0gdG9GbG9hdChmeSk7XG4gICAgICAgICAgICAgICAgcG93KGZ4IC0gLjUsIDIpICsgcG93KGZ5IC0gLjUsIDIpID4gLjI1ICYmIChmeSA9IG1hdGguc3FydCguMjUgLSBwb3coZnggLSAuNSwgMikpICogKChmeSA+IC41KSAqIDIgLSAxKSArIC41KTtcbiAgICAgICAgICAgICAgICBmeGZ5ID0gZnggKyBTICsgZnk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRTtcbiAgICAgICAgfSk7XG4gICAgICAgIGdyYWRpZW50ID0gZ3JhZGllbnQuc3BsaXQoL1xccypcXC1cXHMqLyk7XG4gICAgICAgIGlmICh0eXBlID09IFwibGluZWFyXCIpIHtcbiAgICAgICAgICAgIHZhciBhbmdsZSA9IGdyYWRpZW50LnNoaWZ0KCk7XG4gICAgICAgICAgICBhbmdsZSA9IC10b0Zsb2F0KGFuZ2xlKTtcbiAgICAgICAgICAgIGlmIChpc05hTihhbmdsZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgI
57612H1cbiAgICAgICAgfVxuICAgICAgICB2YXIgZG90cyA9IFIuX3BhcnNlRG90cyhncmFkaWVudCk7XG4gICAgICAgIGlmICghZG90cykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgbyA9IG8uc2hhcGUgfHwgby5ub2RlO1xuICAgICAgICBpZiAoZG90cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIG8ucmVtb3ZlQ2hpbGQoZmlsbCk7XG4gICAgICAgICAgICBmaWxsLm9uID0gdHJ1ZTtcbiAgICAgICAgICAgIGZpbGwubWV0aG9kID0gXCJub25lXCI7XG4gICAgICAgICAgICBmaWxsLmNvbG9yID0gZG90c1swXS5jb2xvcjtcbiAgICAgICAgICAgIGZpbGwuY29sb3IyID0gZG90c1tkb3RzLmxlbmd0aCAtIDFdLmNvbG9yO1xuICAgICAgICAgICAgdmFyIGNscnMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGRvdHMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGRvdHNbaV0ub2Zmc2V0ICYmIGNscnMucHVzaChkb3RzW2ldLm9mZnNldCArIFMgKyBkb3RzW2ldLmNvbG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbGwuY29sb3JzID0gY2xycy5sZW5ndGggPyBjbHJzLmpvaW4oKSA6IFwiMCUgXCIgKyBmaWxsLmNvbG9yO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJyYWRpYWxcIikge1xuICAgICAgICAgICAgICAgIGZpbGwudHlwZSA9IFwiZ3JhZGllbnRUaXRsZVwiO1xuICAgICAgICAgICAgICAgIGZpbGwuZm9jdXMgPSBcIjEwMCVcIjtcbiAgICAgICAgICAgICAgICBmaWxsLmZvY3Vzc2l6ZSA9IFwiMCAwXCI7XG4gICAgICAgICAgICAgICAgZmlsbC5mb2N1c3Bvc2l0aW9uID0gZnhmeTtcbiAgICAgICAgICAgICAgICBmaWxsLmFuZ2xlID0gMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZmlsbC5yb3RhdGU9IHRydWU7XG4gICAgICAgICAgICAgICAgZmlsbC50eXBlID0gXCJncmFkaWVudFwiO1xuICAgICAgICAgICAgICAgIGZpbGwuYW5nbGUgPSAoMjcwIC0gYW5nbGUpICUgMzYwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgby5hcHBlbmRDaGlsZChmaWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMTtcbiAgICB9LFxuICAgIEVsZW1lbnQgPSBmdW5jdGlvbiAobm9kZSwgdm1sKSB7XG4gICAgICAgIHRoaXNbMF0gPSB0aGlzLm5vZGUgPSBub2RlO1xuICAgICAgICBub2RlLnJhcGhhZWwgPSB0cnVlO1xuICAgICAgICB0aGlzLmlkID0gUi5fb2lkKys7XG4gICAgICAgIG5vZGUucmFwaGFlbGlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy5YID0gMDtcbiAgICAgICAgdGhpcy5ZID0gMDtcbiAgICAgICAgdGhpcy5hdHRycyA9IHt9O1xuICAgICAgICB0aGlzLnBhcGVyID0gdm1sO1xuICAgICAgICB0aGlzLm1hdHJpeCA9IFIubWF0cml4KCk7XG4gICAgICAgIHRoaXMuXyA9IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogW10sXG4gICAgICAgICAgICBzeDogMSxcbiAgICAgICAgICAgIHN5OiAxLFxuICAgICAgICAgICAgZHg6IDAsXG4gICAgICAgICAgICBkeTogMCxcbiAgICAgICAgICAgIGRlZzogMCxcbiAgICAgICAgICAgIGRpcnR5OiAxLFxuICAgICAgICAgICAgZGlydHlUOiAxXG4gICAgICAgIH07XG4gICAgICAgICF2bWwuYm90dG9tICYmICh2bWwuYm90dG9tID0gdGhpcyk7XG4gICAgICAgIHRoaXMucHJldiA9IHZtbC50b3A7XG4gICAgICAgIHZtbC50b3AgJiYgKHZtbC50b3AubmV4dCA9IHRoaXMpO1xuICAgICAgICB2bWwudG9wID0gdGhpcztcbiAgICAgICAgdGhpcy5uZXh0ID0gbnVsbDtcbiAgICB9O1xuICAgIHZhciBlbHByb3RvID0gUi5lbDtcblxuICAgIEVsZW1lbnQucHJvdG90eXBlID0gZWxwcm90bztcbiAgICBlbHByb3RvLmNvbnN0cnVjdG9yID0gRWxlbWVudDtcbiAgICBlbHByb3RvLnRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0c3RyKSB7XG4gICAgICAgIGlmICh0c3RyID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl8udHJhbnNmb3JtO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2YnMgPSB0aGlzLnBhcGVyLl92aWV3Qm94U2hpZnQsXG4gICAgICAgICAgICB2YnQgPSB2YnMgPyBcInNcIiArIFt2YnMuc2NhbGUsIHZicy5zY2FsZV0gKyBcIi0xLTF0XCIgKyBbdmJzLmR4LCB2YnMuZHldIDogRSxcbiAgICAgICAgICAgIG9sZHQ7XG4gICAgICAgIGlmICh2YnMpIHtcbiAgICAgICAgICAgIG9sZHQgPSB0c3RyID0gU3RyKHRzdHIpLnJlcGxhY2UoL1xcLnszfXxcXHUyMDI2L2csIHRoaXMuXy50cmFuc2Zvcm0gfHwgRSk7XG4gICAgICAgIH1cbiAgICAgICAgUi5fZXh0cmFjdFRyYW5zZm9ybSh0aGlzLCB2YnQgKyB0c3RyKTtcbiAgICAgICAgdmFyIG1hdHJpeCA9IHRoaXMubWF0cml4LmNsb25lKCksXG4gICAgICAgICAgICBza2V3ID0gdGhpcy5za2V3LFxuICAgICAgICAgICAgbyA9IHRoaXMubm9kZSxcbiAgICAgICAgICAgIHNwbGl0LFxuICAgICAgICAgICAgaXNHcmFkID0gflN0cih0aGlzLmF0dHJzLmZpbGwpLmluZGV4T2YoXCItXCIpLFxuICAgICAgICAgICAgaXNQYXR0ID0gIVN0cih0aGlzLmF0dHJzLmZpbGwpLmluZGV4T2YoXCJ1cmwoXCIpO1xuICAgICAgICBtYXRyaXgudHJhbnNsYXRlKDEsIDEpO1xuICAgICAgICBpZiAoaXNQYXR0IHx8IGlzR3JhZCB8fCB0aGlzLnR5cGUgPT0gXCJpbWFnZVwiKSB7XG4gICAgICAgICAgICBza2V3Lm1hdHJpeCA9IFwiMSAwIDAgMVwiO1xuICAgICAgICAgICAgc2tldy5vZmZzZXQgPSBcIjAgMFwiO1xuICAgICAgICAgICAgc3BsaXQgPSBtYXRyaXguc3BsaXQoKTtcbiAgICAgICAgICAgIGlmICgoaXNHcmFkICYmIHNwbGl0Lm5vUm90YXRpb24pIHx8ICFzcGxpdC5pc1NpbXBsZSkge1xuICAgICAgICAgICAgICAgIG8uc3R5bGUuZmlsdGVyID0gbWF0cml4LnRvRmlsdGVyKCk7XG4gICAgICAgICAgICAgICAgdmFyIGJiID0gdGhpcy5nZXRCQm94KCksXG4gICAgICAgICAgICAgICAgICAgIGJidCA9IHRoaXMuZ2V0QkJveCgxKSxcbiAgICAgICAgICAgICAgICAgICAgZHggPSBiYi54IC0gYmJ0LngsXG4gICAgICAgICAgICAgICAgICAgIGR5ID0gYmIueSAtIGJidC55O1xuICAgICAgICAgICAgICAgIG8uY29vcmRvcmlnaW4gPSAoZHggKiAtem9vbSkgKyBTICsgKGR5ICogLXpvb20pO1xuICAgICAgICAgICAgICAgI
57612HNldENvb3Jkcyh0aGlzLCAxLCAxLCBkeCwgZHksIDApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvLnN0eWxlLmZpbHRlciA9IEU7XG4gICAgICAgICAgICAgICAgc2V0Q29vcmRzKHRoaXMsIHNwbGl0LnNjYWxleCwgc3BsaXQuc2NhbGV5LCBzcGxpdC5keCwgc3BsaXQuZHksIHNwbGl0LnJvdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvLnN0eWxlLmZpbHRlciA9IEU7XG4gICAgICAgICAgICBza2V3Lm1hdHJpeCA9IFN0cihtYXRyaXgpO1xuICAgICAgICAgICAgc2tldy5vZmZzZXQgPSBtYXRyaXgub2Zmc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9sZHQgIT09IG51bGwpIHsgLy8gZW1wdHkgc3RyaW5nIHZhbHVlIGlzIHRydWUgYXMgd2VsbFxuICAgICAgICAgICAgdGhpcy5fLnRyYW5zZm9ybSA9IG9sZHQ7XG4gICAgICAgICAgICBSLl9leHRyYWN0VHJhbnNmb3JtKHRoaXMsIG9sZHQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZWxwcm90by5yb3RhdGUgPSBmdW5jdGlvbiAoZGVnLCBjeCwgY3kpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlZyA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZGVnID0gU3RyKGRlZykuc3BsaXQoc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKGRlZy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBjeCA9IHRvRmxvYXQoZGVnWzFdKTtcbiAgICAgICAgICAgIGN5ID0gdG9GbG9hdChkZWdbMl0pO1xuICAgICAgICB9XG4gICAgICAgIGRlZyA9IHRvRmxvYXQoZGVnWzBdKTtcbiAgICAgICAgKGN5ID09IG51bGwpICYmIChjeCA9IGN5KTtcbiAgICAgICAgaWYgKGN4ID09IG51bGwgfHwgY3kgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJCb3goMSk7XG4gICAgICAgICAgICBjeCA9IGJib3gueCArIGJib3gud2lkdGggLyAyO1xuICAgICAgICAgICAgY3kgPSBiYm94LnkgKyBiYm94LmhlaWdodCAvIDI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fLmRpcnR5VCA9IDE7XG4gICAgICAgIHRoaXMudHJhbnNmb3JtKHRoaXMuXy50cmFuc2Zvcm0uY29uY2F0KFtbXCJyXCIsIGRlZywgY3gsIGN5XV0pKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChkeCwgZHkpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZHggPSBTdHIoZHgpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChkeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBkeSA9IHRvRmxvYXQoZHhbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGR4ID0gdG9GbG9hdChkeFswXSkgfHwgMDtcbiAgICAgICAgZHkgPSArZHkgfHwgMDtcbiAgICAgICAgaWYgKHRoaXMuXy5iYm94KSB7XG4gICAgICAgICAgICB0aGlzLl8uYmJveC54ICs9IGR4O1xuICAgICAgICAgICAgdGhpcy5fLmJib3gueSArPSBkeTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyYW5zZm9ybSh0aGlzLl8udHJhbnNmb3JtLmNvbmNhdChbW1widFwiLCBkeCwgZHldXSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIGVscHJvdG8uc2NhbGUgPSBmdW5jdGlvbiAoc3gsIHN5LCBjeCwgY3kpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgc3ggPSBTdHIoc3gpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChzeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBzeSA9IHRvRmxvYXQoc3hbMV0pO1xuICAgICAgICAgICAgY3ggPSB0b0Zsb2F0KHN4WzJdKTtcbiAgICAgICAgICAgIGN5ID0gdG9GbG9hdChzeFszXSk7XG4gICAgICAgICAgICBpc05hTihjeCkgJiYgKGN4ID0gbnVsbCk7XG4gICAgICAgICAgICBpc05hTihjeSkgJiYgKGN5ID0gbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgc3ggPSB0b0Zsb2F0KHN4WzBdKTtcbiAgICAgICAgKHN5ID09IG51bGwpICYmIChzeSA9IHN4KTtcbiAgICAgICAgKGN5ID09IG51bGwpICYmIChjeCA9IGN5KTtcbiAgICAgICAgaWYgKGN4ID09IG51bGwgfHwgY3kgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJCb3goMSk7XG4gICAgICAgIH1cbiAgICAgICAgY3ggPSBjeCA9PSBudWxsID8gYmJveC54ICsgYmJveC53aWR0aCAvIDIgOiBjeDtcbiAgICAgICAgY3kgPSBjeSA9PSBudWxsID8gYmJveC55ICsgYmJveC5oZWlnaHQgLyAyIDogY3k7XG5cbiAgICAgICAgdGhpcy50cmFuc2Zvcm0odGhpcy5fLnRyYW5zZm9ybS5jb25jYXQoW1tcInNcIiwgc3gsIHN5LCBjeCwgY3ldXSkpO1xuICAgICAgICB0aGlzLl8uZGlydHlUID0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICF0aGlzLnJlbW92ZWQgJiYgKHRoaXMubm9kZS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIGVscHJvdG8uc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgIXRoaXMucmVtb3ZlZCAmJiAodGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPSBFKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvLyBOZWVkZWQgdG8gZml4IHRoZSB2bWwgc2V0Vmlld0JveCBpc3N1ZXNcbiAgICBlbHByb3RvLmF1eEdldEJCb3ggPSBSLmVsLmdldEJCb3g7XG4gICAgZWxwcm90by5nZXRCQm94ID0gZnVuY3Rpb24oKXtcbiAgICAgIHZhciBiID0gdGhpcy5hdXhHZXRCQm94KCk7XG4gICAgICBpZiAodGhpcy5wYXBlciAmJiB0aGlzLnBhcGVyLl92aWV3Qm94U2hpZnQpXG4gICAgICB7XG4gICAgICAgIHZhciBjID0ge307XG4gICAgICAgIHZhciB6ID0gMS90aGlzLnBhcGVyLl92aWV3Qm94U2hpZnQuc2NhbGU7XG4gICAgICAgIGMueCA9IGIueCAtIHRoaXMucGFwZXIuX3ZpZXdCb3hTaGlmdC5keDtcbiAgICAgICAgYy54ICo9IHo7XG4gICAgICAgIGMueSA9IGIueSAtIHRoaXMucGFwZXIuX3ZpZXdCb3hTaGlmdC5keTtcbiAgICAgICAgYy55ICo9IHo7XG4gICAgICAgIGMud2lkdGggID0gYi53aWR0aCAgKiB6O1xuICAgICAgICBjLmhlaWdodCA9IGIuaGVpZ2h0ICogejtcbiAgICAgICAgYy54MiA9IGMueCArIGMud2lkdGg7XG4gICAgICAgIGMueTIgPSBjLnkgKyBjLmhlaWdodDtcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgICB9XG4gICAgICByZXR1cm4gYjtcbiAgICB9O1xuICAgIGVscHJvdG8uX2dldEJCb3ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgI
57612HJldHVybiB7fTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogdGhpcy5YICsgKHRoaXMuYmJ4IHx8IDApIC0gdGhpcy5XIC8gMixcbiAgICAgICAgICAgIHk6IHRoaXMuWSAtIHRoaXMuSCxcbiAgICAgICAgICAgIHdpZHRoOiB0aGlzLlcsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMuSFxuICAgICAgICB9O1xuICAgIH07XG4gICAgZWxwcm90by5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQgfHwgIXRoaXMubm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXBlci5fX3NldF9fICYmIHRoaXMucGFwZXIuX19zZXRfXy5leGNsdWRlKHRoaXMpO1xuICAgICAgICBSLmV2ZS51bmJpbmQoXCJyYXBoYWVsLiouKi5cIiArIHRoaXMuaWQpO1xuICAgICAgICBSLl90ZWFyKHRoaXMsIHRoaXMucGFwZXIpO1xuICAgICAgICB0aGlzLm5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLm5vZGUpO1xuICAgICAgICB0aGlzLnNoYXBlICYmIHRoaXMuc2hhcGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLnNoYXBlKTtcbiAgICAgICAgZm9yICh2YXIgaSBpbiB0aGlzKSB7XG4gICAgICAgICAgICB0aGlzW2ldID0gdHlwZW9mIHRoaXNbaV0gPT0gXCJmdW5jdGlvblwiID8gUi5fcmVtb3ZlZEZhY3RvcnkoaSkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlZCA9IHRydWU7XG4gICAgfTtcbiAgICBlbHByb3RvLmF0dHIgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5hbWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgYSBpbiB0aGlzLmF0dHJzKSBpZiAodGhpcy5hdHRyc1toYXNdKGEpKSB7XG4gICAgICAgICAgICAgICAgcmVzW2FdID0gdGhpcy5hdHRyc1thXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcy5ncmFkaWVudCAmJiByZXMuZmlsbCA9PSBcIm5vbmVcIiAmJiAocmVzLmZpbGwgPSByZXMuZ3JhZGllbnQpICYmIGRlbGV0ZSByZXMuZ3JhZGllbnQ7XG4gICAgICAgICAgICByZXMudHJhbnNmb3JtID0gdGhpcy5fLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwgJiYgUi5pcyhuYW1lLCBcInN0cmluZ1wiKSkge1xuICAgICAgICAgICAgaWYgKG5hbWUgPT0gZmlsbFN0cmluZyAmJiB0aGlzLmF0dHJzLmZpbGwgPT0gXCJub25lXCIgJiYgdGhpcy5hdHRycy5ncmFkaWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmF0dHJzLmdyYWRpZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG5hbWVzID0gbmFtZS5zcGxpdChzZXBhcmF0b3IpLFxuICAgICAgICAgICAgICAgIG91dCA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBuYW1lc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZSBpbiB0aGlzLmF0dHJzKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dFtuYW1lXSA9IHRoaXMuYXR0cnNbbmFtZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChSLmlzKHRoaXMucGFwZXIuY3VzdG9tQXR0cmlidXRlc1tuYW1lXSwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgICAgICAgICBvdXRbbmFtZV0gPSB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbbmFtZV0uZGVmO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dFtuYW1lXSA9IFIuX2F2YWlsYWJsZUF0dHJzW25hbWVdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpaSAtIDEgPyBvdXQgOiBvdXRbbmFtZXNbMF1dO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmF0dHJzICYmIHZhbHVlID09IG51bGwgJiYgUi5pcyhuYW1lLCBcImFycmF5XCIpKSB7XG4gICAgICAgICAgICBvdXQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gbmFtZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgb3V0W25hbWVbaV1dID0gdGhpcy5hdHRyKG5hbWVbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfVxuICAgICAgICB2Y
57612XIgcGFyYW1zO1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcGFyYW1zID0ge307XG4gICAgICAgICAgICBwYXJhbXNbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZSA9PSBudWxsICYmIFIuaXMobmFtZSwgXCJvYmplY3RcIikgJiYgKHBhcmFtcyA9IG5hbWUpO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmF0dHIuXCIgKyBrZXkgKyBcIi5cIiArIHRoaXMuaWQsIHRoaXMsIHBhcmFtc1trZXldKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zKSB7XG4gICAgICAgICAgICBmb3IgKGtleSBpbiB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXMpIGlmICh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbaGFzXShrZXkpICYmIHBhcmFtc1toYXNdKGtleSkgJiYgUi5pcyh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNba2V5XSwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXIgPSB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNba2V5XS5hcHBseSh0aGlzLCBbXS5jb25jYXQocGFyYW1zW2tleV0pKTtcbiAgICAgICAgICAgICAgICB0aGlzLmF0dHJzW2tleV0gPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBzdWJrZXkgaW4gcGFyKSBpZiAocGFyW2hhc10oc3Via2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbc3Via2V5XSA9IHBhcltzdWJrZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRoaXMucGFwZXIuY2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgIGlmIChwYXJhbXMudGV4dCAmJiB0aGlzLnR5cGUgPT0gXCJ0ZXh0XCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHRwYXRoLnN0cmluZyA9IHBhcmFtcy50ZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2V0RmlsbEFuZFN0cm9rZSh0aGlzLCBwYXJhbXMpO1xuICAgICAgICAgICAgLy8gdGhpcy5wYXBlci
576125jYW52YXMuc3R5bGUuZGlzcGxheSA9IEU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLnRvRnJvbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICF0aGlzLnJlbW92ZWQgJiYgdGhpcy5ub2RlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQodGhpcy5ub2RlKTtcbiAgICAgICAgdGhpcy5wYXBlciAmJiB0aGlzLnBhcGVyLnRvcCAhPSB0aGlzICYmIFIuX3RvZnJvbnQodGhpcywgdGhpcy5wYXBlcik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZWxwcm90by50b0JhY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm5vZGUucGFyZW50Tm9kZS5maXJzdENoaWxkICE9IHRoaXMubm9kZSkge1xuICAgICAgICAgICAgdGhpcy5ub2RlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMubm9kZSwgdGhpcy5ub2RlLnBhcmVudE5vZGUuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICBSLl90b2JhY2sodGhpcywgdGhpcy5wYXBlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmluc2VydEFmdGVyID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVsZW1lbnQuY29uc3RydWN0b3IgPT0gUi5zdC5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgZWxlbWVudCA9IGVsZW1lbnRbZWxlbWVudC5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWxlbWVudC5ub2RlLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgICBlbGVtZW50Lm5vZGUucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5ub2RlLCBlbGVtZW50Lm5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWxlbWVudC5ub2RlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQodGhpcy5ub2RlKTtcbiAgICAgICAgfVxuICAgICAgICBSLl9pbnNlcnRhZnRlcih0aGlzLCBlbGVtZW50LCB0aGlzLnBhcGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmluc2VydEJlZm9yZSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbGVtZW50LmNvbnN0cnVjdG9yID09IFIuc3QuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIGVsZW1lbnQgPSBlbGVtZW50WzBdO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQubm9kZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLm5vZGUsIGVsZW1lbnQubm9kZSk7XG4gICAgICAgIFIuX2luc2VydGJlZm9yZSh0aGlzLCBlbGVtZW50LCB0aGlzLnBhcGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmJsdXIgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICB2Y
57612XIgcyA9IHRoaXMubm9kZS5ydW50aW1lU3R5bGUsXG4gICAgICAgICAgICBmID0gcy5maWx0ZXI7XG4gICAgICAgIGYgPSBmLnJlcGxhY2UoYmx1cnJlZ2V4cCwgRSk7XG4gICAgICAgIGlmICgrc2l6ZSAhPT0gMCkge1xuICAgICAgICAgICAgdGhpcy5hdHRycy5ibHVyID0gc2l6ZTtcbiAgICAgICAgICAgIHMuZmlsdGVyID0gZiArIFMgKyBtcyArIFwiLkJsdXIocGl4ZWxyYWRpdXM9XCIgKyAoK3NpemUgfHwgMS41KSArIFwiKVwiO1xuICAgICAgICAgICAgcy5tYXJnaW4gPSBSLmZvcm1hdChcIi17MH1weCAwIDAgLXswfXB4XCIsIHJvdW5kKCtzaXplIHx8IDEuNSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcy5maWx0ZXIgPSBmO1xuICAgICAgICAgICAgcy5tYXJnaW4gPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYXR0cnMuYmx1cjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgUi5fZW5naW5lLnBhdGggPSBmdW5jdGlvbiAocGF0aFN0cmluZywgdm1sKSB7XG4gICAgICAgIHZhciBlbCA9IGNyZWF0ZU5vZGUoXCJzaGFwZVwiKTtcbiAgICAgICAgZWwuc3R5bGUuY3NzVGV4dCA9IGNzc0RvdDtcbiAgICAgICAgZWwuY29vcmRzaXplID0gem9vbSArIFMgKyB6b29tO1xuICAgICAgICBlbC5jb29yZG9yaWdpbiA9IHZtbC5jb29yZG9yaWdpbjtcbiAgICAgICAgdmFyIHAgPSBuZXcgRWxlbWVudChlbCwgdm1sKSxcbiAgICAgICAgICAgIGF0dHIgPSB7ZmlsbDogXCJub25lXCIsIHN0cm9rZTogXCIjMDAwXCJ9O1xuICAgICAgICBwYXRoU3RyaW5nICYmIChhdHRyLnBhdGggPSBwYXRoU3RyaW5nKTtcbiAgICAgICAgcC50eXBlID0gXCJwYXRoXCI7XG4gICAgICAgIHAucGF0aCA9IFtdO1xuICAgICAgICBwLlBhdGggPSBFO1xuICAgICAgICBzZXRGaWxsQW5kU3Ryb2tlKHAsIGF0dHIpO1xuICAgICAgICB2bWwuY2FudmFzICYmIHZtbC5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2Y
57612XIgc2tldyA9IGNyZWF0ZU5vZGUoXCJza2V3XCIpO1xuICAgICAgICBza2V3Lm9uID0gdHJ1ZTtcbiAgICAgICAgZWwuYXBwZW5kQ2hpbGQoc2tldyk7XG4gICAgICAgIHAuc2tldyA9IHNrZXc7XG4gICAgICAgIHAudHJhbnNmb3JtKEUpO1xuICAgICAgICByZXR1cm4gcDtcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5yZWN0ID0gZnVuY3Rpb24gKHZtbCwgeCwgeSwgdywgaCwgcikge1xuICAgICAgICB2YXIgcGF0aCA9IFIuX3JlY3RQYXRoKHgsIHksIHcsIGgsIHIpLFxuICAgICAgICAgICAgcmVzID0gdm1sLnBhdGgocGF0aCksXG4gICAgICAgICAgICBhID0gcmVzLmF0dHJzO1xuICAgICAgICByZXMuWCA9IGEueCA9IHg7XG4gICAgICAgIHJlcy5ZID0gYS55ID0geTtcbiAgICAgICAgcmVzLlcgPSBhLndpZHRoID0gdztcbiAgICAgICAgcmVzLkggPSBhLmhlaWdodCA9IGg7XG4gICAgICAgIGEuciA9IHI7XG4gICAgICAgIGEucGF0aCA9IHBhdGg7XG4gICAgICAgIHJlcy50eXBlID0gXCJyZWN0XCI7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuZWxsaXBzZSA9IGZ1bmN0aW9uICh2bWwsIHgsIHksIHJ4LCByeSkge1xuICAgICAgICB2YXIgcmVzID0gdm1sLnBhdGgoKSxcbiAgICAgICAgICAgIGEgPSByZXMuYXR0cnM7XG4gICAgICAgIHJlcy5YID0geCAtIHJ4O1xuICAgICAgICByZXMuWSA9IHkgLSByeTtcbiAgICAgICAgcmVzLlcgPSByeCAqIDI7XG4gICAgICAgIHJlcy5IID0gcnkgKiAyO1xuICAgICAgICByZXMudHlwZSA9IFwiZWxsaXBzZVwiO1xuICAgICAgICBzZXRGaWxsQW5kU3Ryb2tlKHJlcywge1xuICAgICAgICAgICAgY3g6IHgsXG4gICAgICAgICAgICBjeTogeSxcbiAgICAgICAgICAgIHJ4OiByeCxcbiAgICAgICAgICAgIHJ5OiByeVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5jaXJjbGUgPSBmdW5jdGlvbiAodm1sLCB4LCB5LCByKSB7XG4gICAgICAgIHZhciByZXMgPSB2bWwucGF0aCgpLFxuICAgICAgICAgICAgYSA9IHJlcy5hdHRycztcbiAgICAgICAgcmVzLlggPSB4IC0gcjtcbiAgICAgICAgcmVzLlkgPSB5IC0gcjtcbiAgICAgICAgcmVzLlcgPSByZXMuSCA9IHIgKiAyO1xuICAgICAgICByZXMudHlwZSA9IFwiY2lyY2xlXCI7XG4gICAgICAgIHNldEZpbGxBbmRTdHJva2UocmVzLCB7XG4gICAgICAgICAgICBjeDogeCxcbiAgICAgICAgICAgIGN5OiB5LFxuICAgICAgICAgICAgcjogclxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5pbWFnZSA9IGZ1bmN0aW9uICh2bWwsIHNyYywgeCwgeSwgdywgaCkge1xuICAgICAgICB2Y
57612XIgcGF0aCA9IFIuX3JlY3RQYXRoKHgsIHksIHcsIGgpLFxuICAgICAgICAgICAgcmVzID0gdm1sLnBhdGgocGF0aCkuYXR0cih7c3Ryb2tlOiBcIm5vbmVcIn0pLFxuICAgICAgICAgICAgYSA9IHJlcy5hdHRycyxcbiAgICAgICAgICAgIG5vZGUgPSByZXMubm9kZSxcbiAgICAgICAgICAgIGZpbGwgPSBub2RlLmdldEVsZW1lbnRzQnlUYWdOYW1lKGZpbGxTdHJpbmcpWzBdO1xuICAgICAgICBhLnNyYyA9IHNyYztcbiAgICAgICAgcmVzLlggPSBhLnggPSB4O1xuICAgICAgICByZXMuWSA9IGEueSA9IHk7XG4gICAgICAgIHJlcy5XID0gYS53aWR0aCA9IHc7XG4gICAgICAgIHJlcy5IID0gYS5oZWlnaHQgPSBoO1xuICAgICAgICBhLnBhdGggPSBwYXRoO1xuICAgICAgICByZXMudHlwZSA9IFwiaW1hZ2VcIjtcbiAgICAgICAgZmlsbC5wYXJlbnROb2RlID09IG5vZGUgJiYgbm9kZS5yZW1vdmVDaGlsZChmaWxsKTtcbiAgICAgICAgZmlsbC5yb3RhdGUgPSB0cnVlO1xuICAgICAgICBmaWxsLnNyYyA9IHNyYztcbiAgICAgICAgZmlsbC50eXBlID0gXCJ0aWxlXCI7XG4gICAgICAgIHJlcy5fLmZpbGxwb3MgPSBbeCwgeV07XG4gICAgICAgIHJlcy5fLmZpbGxzaXplID0gW3csIGhdO1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKGZpbGwpO1xuICAgICAgICBzZXRDb29yZHMocmVzLCAxLCAxLCAwLCAwLCAwKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS50ZXh0ID0gZnVuY3Rpb24gKHZtbCwgeCwgeSwgdGV4dCkge1xuICAgICAgICB2Y
57612XIgZWwgPSBjcmVhdGVOb2RlKFwic2hhcGVcIiksXG4gICAgICAgICAgICBwYXRoID0gY3JlYXRlTm9kZShcInBhdGhcIiksXG4gICAgICAgICAgICBvID0gY3JlYXRlTm9kZShcInRleHRwYXRoXCIpO1xuICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICB5ID0geSB8fCAwO1xuICAgICAgICB0ZXh0ID0gdGV4dCB8fCBcIlwiO1xuICAgICAgICBwYXRoLnYgPSBSLmZvcm1hdChcIm17MH0sezF9bHsyfSx7MX1cIiwgcm91bmQoeCAqIHpvb20pLCByb3VuZCh5ICogem9vbSksIHJvdW5kKHggKiB6b29tKSArIDEpO1xuICAgICAgICBwYXRoLnRleHRwYXRob2sgPSB0cnVlO1xuICAgICAgICBvLnN0cmluZyA9IFN0cih0ZXh0KTtcbiAgICAgICAgby5vbiA9IHRydWU7XG4gICAgICAgIGVsLnN0eWxlLmNzc1RleHQgPSBjc3NEb3Q7XG4gICAgICAgIGVsLmNvb3Jkc2l6ZSA9IHpvb20gKyBTICsgem9vbTtcbiAgICAgICAgZWwuY29vcmRvcmlnaW4gPSBcIjAgMFwiO1xuICAgICAgICB2YXIgcCA9IG5ldyBFbGVtZW50KGVsLCB2bWwpLFxuICAgICAgICAgICAgYXR0ciA9IHtcbiAgICAgICAgICAgICAgICBmaWxsOiBcIiMwMDBcIixcbiAgICAgICAgICAgICAgICBzdHJva2U6IFwibm9uZVwiLFxuICAgICAgICAgICAgICAgIGZvbnQ6IFIuX2F2YWlsYWJsZUF0dHJzLmZvbnQsXG4gICAgICAgICAgICAgICAgdGV4dDogdGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgcC5zaGFwZSA9IGVsO1xuICAgICAgICBwLnBhdGggPSBwYXRoO1xuICAgICAgICBwLnRleHRwYXRoID0gbztcbiAgICAgICAgcC50eXBlID0gXCJ0ZXh0XCI7XG4gICAgICAgIHAuYXR0cnMudGV4dCA9IFN0cih0ZXh0KTtcbiAgICAgICAgcC5hdHRycy54ID0geDtcbiAgICAgICAgcC5hdHRycy55ID0geTtcbiAgICAgICAgcC5hdHRycy53ID0gMTtcbiAgICAgICAgcC5hdHRycy5oID0gMTtcbiAgICAgICAgc2V0RmlsbEFuZFN0cm9rZShwLCBhdHRyKTtcbiAgICAgICAgZWwuYXBwZW5kQ2hpbGQobyk7XG4gICAgICAgIGVsLmFwcGVuZENoaWxkKHBhdGgpO1xuICAgICAgICB2bWwuY2FudmFzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgdmFyIHNrZXcgPSBjcmVhdGVOb2RlKFwic2tld1wiKTtcbiAgICAgICAgc2tldy5vbiA9IHRydWU7XG4gICAgICAgIGVsLmFwcGVuZENoaWxkKHNrZXcpO1xuICAgICAgICBwLnNrZXcgPSBza2V3O1xuICAgICAgICBwLnRyYW5zZm9ybShFKTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuc2V0U2l6ZSA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIHZhciBjcyA9IHRoaXMuY2FudmFzLnN0eWxlO1xuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICB3aWR0aCA9PSArd2lkdGggJiYgKHdpZHRoICs9IFwicHhcIik7XG4gICAgICAgIGhlaWdodCA9PSAraGVpZ2h0ICYmIChoZWlnaHQgKz0gXCJweFwiKTtcbiAgICAgICAgY3Mud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY3MuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICBjcy5jbGlwID0gXCJyZWN0KDAgXCIgKyB3aWR0aCArIFwiIFwiICsgaGVpZ2h0ICsgXCIgMClcIjtcbiAgICAgICAgaWYgKHRoaXMuX3ZpZXdCb3gpIHtcbiAgICAgICAgICAgIFIuX2VuZ2luZS5zZXRWaWV3Qm94LmFwcGx5KHRoaXMsIHRoaXMuX3ZpZXdCb3gpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLnNldFZpZXdCb3ggPSBmdW5jdGlvbiAoeCwgeSwgdywgaCwgZml0KSB7XG4gICAgICAgIFIuZXZlKFwicmFwaGFlbC5zZXRWaWV3Qm94XCIsIHRoaXMsIHRoaXMuX3ZpZXdCb3gsIFt4LCB5LCB3LCBoLCBmaXRdKTtcbiAgICAgICAgdmFyIHBhcGVyU2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxuICAgICAgICAgICAgd2lkdGggPSBwYXBlclNpemUud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQgPSBwYXBlclNpemUuaGVpZ2h0LFxuICAgICAgICAgICAgSCwgVztcbiAgICAgICAgaWYgKGZpdCkge1xuICAgICAgICAgICAgSCA9IGhlaWdodCAvIGg7XG4gICAgICAgICAgICBXID0gd2lkdGggLyB3O1xuICAgICAgICAgICAgaWYgKHcgKiBIIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICB4IC09ICh3aWR0aCAtIHcgKiBIKSAvIDIgLyBIO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGggKiBXIDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgeSAtPSAoaGVpZ2h0IC0gaCAqIFcpIC8gMiAvIFc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmlld0JveCA9IFt4LCB5LCB3LCBoLCAhIWZpdF07XG4gICAgICAgIHRoaXMuX3ZpZXdCb3hTaGlmdCA9IHtcbiAgICAgICAgICAgIGR4OiAteCxcbiAgICAgICAgICAgIGR5OiAteSxcbiAgICAgICAgICAgIHNjYWxlOiBwYXBlclNpemVcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgZWwudHJhbnNmb3JtKFwiLi4uXCIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICB2YXIgY3JlYXRlTm9kZTtcbiAgICBSLl9lbmdpbmUuaW5pdFdpbiA9IGZ1bmN0aW9uICh3aW4pIHtcbiAgICAgICAgICAgIHZhciBkb2MgPSB3aW4uZG9jdW1lbnQ7XG4gICAgICAgICAgICBpZiAoZG9jLnN0eWxlU2hlZXRzLmxlbmd0aCA8IDMxKSB7XG4gICAgICAgICAgICAgICAgZG9jLmNyZWF0ZVN0eWxlU2hlZXQoKS5hZGRSdWxlKFwiLnJ2bWxcIiwgXCJiZWhhdmlvcjp1cmwoI2RlZmF1bHQjVk1MKVwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gbm8gbW9yZSByb29tLCBhZGQgdG8gdGhlIGV4aXN0aW5nIG9uZVxuICAgICAgICAgICAgICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzMTE5NCUyOFZTLjg1JTI5LmFzcHhcbiAgICAgICAgICAgICAgICBkb2Muc3R5bGVTaGVldHNbMF0uYWRkUnVsZShcIi5ydm1sXCIsIFwiYmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTClcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIC
57612Fkb2MubmFtZXNwYWNlcy5ydm1sICYmIGRvYy5uYW1lc3BhY2VzLmFkZChcInJ2bWxcIiwgXCJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbFwiKTtcbiAgICAgICAgICAgICAgICBjcmVhdGVOb2RlID0gZnVuY3Rpb24gKHRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVFbGVtZW50KCc8cnZtbDonICsgdGFnTmFtZSArICcgY2xhc3M9XCJydm1sXCI+Jyk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjcmVhdGVOb2RlID0gZnVuY3Rpb24gKHRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVFbGVtZW50KCc8JyArIHRhZ05hbWUgKyAnIHhtbG5zPVwidXJuOnNjaGVtYXMtbWljcm9zb2Z0LmNvbTp2bWxcIiBjbGFzcz1cInJ2bWxcIj4nKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIFIuX2VuZ2luZS5pbml0V2luKFIuX2cud2luKTtcbiAgICBSLl9lbmdpbmUuY3JlYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29uID0gUi5fZ2V0Q29udGFpbmVyLmFwcGx5KDAsIGFyZ3VtZW50cyksXG4gICAgICAgICAgICBjb250YWluZXIgPSBjb24uY29udGFpbmVyLFxuICAgICAgICAgICAgaGVpZ2h0ID0gY29uLmhlaWdodCxcbiAgICAgICAgICAgIHMsXG4gICAgICAgICAgICB3aWR0aCA9IGNvbi53aWR0aCxcbiAgICAgICAgICAgIHggPSBjb24ueCxcbiAgICAgICAgICAgIHkgPSBjb24ueTtcbiAgICAgICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlZNTCBjb250YWluZXIgbm90IGZvdW5kLlwiKTtcbiAgICAgICAgfVxuICAgICAgICB2Y
57612XIgcmVzID0gbmV3IFIuX1BhcGVyLFxuICAgICAgICAgICAgYyA9IHJlcy5jYW52YXMgPSBSLl9nLmRvYy5jcmVhdGVFbGVtZW50KFwiZGl2XCIpLFxuICAgICAgICAgICAgY3MgPSBjLnN0eWxlO1xuICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICB5ID0geSB8fCAwO1xuICAgICAgICB3aWR0aCA9IHdpZHRoIHx8IDUxMjtcbiAgICAgICAgaGVpZ2h0ID0gaGVpZ2h0IHx8IDM0MjtcbiAgICAgICAgcmVzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHJlcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIHdpZHRoID09ICt3aWR0aCAmJiAod2lkdGggKz0gXCJweFwiKTtcbiAgICAgICAgaGVpZ2h0ID09ICtoZWlnaHQgJiYgKGhlaWdodCArPSBcInB4XCIpO1xuICAgICAgICByZXMuY29vcmRzaXplID0gem9vbSAqIDFlMyArIFMgKyB6b29tICogMWUzO1xuICAgICAgICByZXMuY29vcmRvcmlnaW4gPSBcIjAgMFwiO1xuICAgICAgICByZXMuc3BhbiA9IFIuX2cuZG9jLmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICByZXMuc3Bhbi5zdHlsZS5jc3NUZXh0ID0gXCJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0Oi05OTk5ZW07dG9wOi05OTk5ZW07cGFkZGluZzowO21hcmdpbjowO2xpbmUtaGVpZ2h0OjE7XCI7XG4gICAgICAgIGMuYXBwZW5kQ2hpbGQocmVzLnNwYW4pO1xuICAgICAgICBjcy5jc3NUZXh0ID0gUi5mb3JtYXQoXCJ0b3A6MDtsZWZ0OjA7d2lkdGg6ezB9O2hlaWdodDp7MX07ZGlzcGxheTppbmxpbmUtYmxvY2s7cG9zaXRpb246cmVsYXRpdmU7Y2xpcDpyZWN0KDAgezB9IHsxfSAwKTtvdmVyZmxvdzpoaWRkZW5cIiwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGlmIChjb250YWluZXIgPT0gMSkge1xuICAgICAgICAgICAgUi5fZy5kb2MuYm9keS5hcHBlbmRDaGlsZChjKTtcbiAgICAgICAgICAgIGNzLmxlZnQgPSB4ICsgXCJweFwiO1xuICAgICAgICAgICAgY3MudG9wID0geSArIFwicHhcIjtcbiAgICAgICAgICAgIGNzLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNvbnRhaW5lci5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmluc2VydEJlZm9yZShjLCBjb250YWluZXIuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXMucmVuZGVyZml4ID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgUi5ldmUoXCJyYXBoYWVsLmNsZWFyXCIsIHRoaXMpO1xuICAgICAgICB0aGlzLmNhbnZhcy5pbm5lckhUTUwgPSBFO1xuICAgICAgICB0aGlzLnNwYW4gPSBSLl9nLmRvYy5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdGhpcy5zcGFuLnN0eWxlLmNzc1RleHQgPSBcInBvc2l0aW9uOmFic29sdXRlO2xlZnQ6LTk5OTllbTt0b3A6LTk5OTllbTtwYWRkaW5nOjA7bWFyZ2luOjA7bGluZS1oZWlnaHQ6MTtkaXNwbGF5OmlubGluZTtcIjtcbiAgICAgICAgdGhpcy5jYW52YXMuYXBwZW5kQ2hpbGQodGhpcy5zcGFuKTtcbiAgICAgICAgdGhpcy5ib3R0b20gPSB0aGlzLnRvcCA9IG51bGw7XG4gICAgfTtcbiAgICBSLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIFIuZXZlKFwicmFwaGFlbC5yZW1vdmVcIiwgdGhpcyk7XG4gICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMpIHtcbiAgICAgICAgICAgIHRoaXNbaV0gPSB0eXBlb2YgdGhpc1tpXSA9PSBcImZ1bmN0aW9uXCIgPyBSLl9yZW1vdmVkRmFjdG9yeShpKSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIHZhciBzZXRwcm90byA9IFIuc3Q7XG4gICAgZm9yICh2YXIgbWV0aG9kIGluIGVscHJvdG8pIGlmIChlbHByb3RvW2hhc10obWV0aG9kKSAmJiAhc2V0cHJvdG9baGFzXShtZXRob2QpKSB7XG4gICAgICAgIHNldHByb3RvW21ldGhvZF0gPSAoZnVuY3Rpb24gKG1ldGhvZG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgICAgICBlbFttZXRob2RuYW1lXS5hcHBseShlbCwgYXJnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pKG1ldGhvZCk7XG4gICAgfVxufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./dev/raphael.vml.js\n");
57613
57614/***/ }),
57615
vendor: 40,047 bytes, lines 57616-57625
57616/***/ "./node_modules/eve-raphael/eve.js":
57617/*!*****************************************!*\
57618  !*** ./node_modules/eve-raphael/eve.js ***!
57619  \*****************************************/
57620/*! no static exports found */
57621/***/ (function(module, exports, __webpack_require__) {
57622
57623eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ┌────────────────────────────────────────────────────────────┐ \\\\\n// │ Eve 0.5.0 - JavaScript Events Library                      │ \\\\\n// ├────────────────────────────────────────────────────────────┤ \\\\\n// │ Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\\\\n// └────────────────────────────────────────────────────────────┘ \\\\\n\n(function (glob) {\n    var version = \"0.5.0\",\n        has = \"hasOwnProperty\",\n        separator = /[\\.\\/]/,\n        comaseparator = /\\s*,\\s*/,\n        wildcard = \"*\",\n        fun = function () {},\n        numsort = function (a, b) {\n            return a - b;\n        },\n        current_event,\n        stop,\n        events = {n: {}},\n        firstDefined = function () {\n            for (var i = 0, ii = this.length; i < ii; i++) {\n                if (typeof this[i] != \"undefined\") {\n                    return this[i];\n                }\n            }\n        },\n        lastDefined = function () {\n            var i = this.length;\n            while (--i) {\n                if (typeof this[i] != \"undefined\") {\n                    return this[i];\n                }\n            }\n        },\n        objtos = Object.prototype.toString,\n        Str = String,\n        isArray = Array.isArray || function (ar) {\n            return ar instanceof Array || objtos.call(ar) == \"[object Array]\";\n        };\n    /*\\\n     * eve\n     [ method ]\n\n     * Fires event with given `name`, given scope and other parameters.\n\n     > Arguments\n\n     - name (string) name of the *event*, dot (`.`) or slash (`/`) separated\n     - scope (object) context for the event handlers\n     - varargs (...) the rest of arguments will be sent to event handlers\n\n     = (object) array of returned values from the listeners. Array has two methods `.firstDefined()` and `.lastDefined()` to get first or last not `undefined` value.\n    \\*/\n        var eve = function (name, scope) {\n            var e = events,\n                oldstop = stop,\n                args = Array.prototype.slice.call(arguments, 2),\n                listeners = eve.listeners(name),\n                z = 0,\n                f = false,\n                l,\n                indexed = [],\n                queue = {},\n                out = [],\n                ce = current_event,\n                errors = [];\n            out.firstDefined = firstDefined;\n            out.lastDefined = lastDefined;\n            current_event = name;\n            stop = 0;\n            for (var i = 0, ii = listeners.length; i < ii; i++) if (\"zIndex\" in listeners[i]) {\n                indexed.push(listeners[i].zIndex);\n                if (listeners[i].zIndex < 0) {\n                    queue[listeners[i].zIndex] = listeners[i];\n                }\n            }\n            indexed.sort(numsort);\n            while (indexed[z] < 0) {\n                l = queue[indexed[z++]];\n                out.push(l.apply(scope, args));\n                if (stop) {\n                    stop = oldstop;\n                    return out;\n                }\n            }\n            for (i = 0; i < ii; i++) {\n                l = listeners[i];\n                if (\"zIndex\" in l) {\n                    if (l.zIndex == indexed[z]) {\n                        out.push(l.apply(scope, args));\n                        if (stop) {\n                            break;\n                        }\n                        do {\n                            z++;\n                            l = queue[indexed[z]];\n                            l && out.push(l.apply(scope, args));\n                            if (stop) {\n                                break;\n                            }\n                        } while (l)\n                    } else {\n                        queue[l.zIndex] = l;\n                    }\n                } else {\n                    out.push(l.apply(scope, args));\n                    if (stop) {\n                        break;\n                    }\n                }\n            }\n            stop = oldstop;\n            current_event = ce;\n            return out;\n        };\n        // Undocumented. Debug only.\n        eve._events = events;\n    /*\\\n     * eve.listeners\n     [ method ]\n\n     * Internal method which gives you array of all event handlers that will be triggered by the given `name`.\n\n     > Arguments\n\n     - name (string) name of the event, dot (`.`) or slash (`/`) separated\n\n     = (array) array of event handlers\n    \\*/\n    eve.listeners = function (name) {\n        var names = isArray(name) ? name : name.split(separator),\n            e = events,\n            item,\n            items,\n            k,\n            i,\n            ii,\n            j,\n            jj,\n            nes,\n            es = [e],\n            out = [];\n        for (i = 0, ii = names.length; i < ii; i++) {\n            nes = [];\n            for (j = 0, jj = es.length; j < jj; j++) {\n                e = es[j].n;\n                items = [e[names[i]], e[wildcard]];\n                k = 2;\n                while (k--) {\n                    item = items[k];\n                    if (item) {\n                        nes.push(item);\n                        out = out.concat(item.f || []);\n                    }\n                }\n            }\n            es = nes;\n        }\n        return out;\n    };\n    /*\\\n     * eve.separator\n     [ method ]\n\n     * If for some reasons you don’t like default separators (`.` or `/`) you can specify yours\n     * here. Be aware that if you pass a string longer than one character it will be treated as\n     * a list of characters.\n\n     - separator (string) new separator. Empty string resets to default: `.` or `/`.\n    \\*/\n    eve.separator = function (sep) {\n        if (sep) {\n            sep = Str(sep).replace(/(?=[\\.\\^\\]\\[\\-])/g, \"\\\\\");\n            sep = \"[\" + sep + \"]\";\n            separator = new RegExp(sep);\n        } else {\n            separator = /[\\.\\/]/;\n        }\n    };\n    /*\\\n     * eve.on\n     [ method ]\n     **\n     * Binds given event handler with a given name. You can use wildcards “`*`” for the names:\n     | eve.on(\"*.under.*\", f);\n     | eve(\"mouse.under.floor\"); // triggers f\n     * Use @eve to trigger the listener.\n     **\n     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n     - f (function) event handler function\n     **\n     - name (array) if you don’t want to use separators, you can use array of strings\n     - f (function) event handler function\n     **\n     = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment. \n     > Example:\n     | eve.on(\"mouse\", eatIt)(2);\n     | eve.on(\"mouse\", scream);\n     | eve.on(\"mouse\", catchIt)(1);\n     * This will ensure that `catchIt` function will be called before `eatIt`.\n     *\n     * If you want to put your handler before non-indexed handlers, specify a negative value.\n     * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”.\n    \\*/\n    eve.on = function (name, f) {\n        if (typeof f != \"function\") {\n            return function () {};\n        }\n        var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);\n        for (var i = 0, ii = names.length; i < ii; i++) {\n            (function (name) {\n                var names = isArray(name) ? name : Str(name).split(separator),\n                    e = events,\n                    exist;\n                for (var i = 0, ii = names.length; i < ii; i++) {\n                    e = e.n;\n                    e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}});\n                }\n                e.f = e.f || [];\n                for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {\n                    exist = true;\n                    break;\n                }\n                !exist && e.f.push(f);\n            }(names[i]));\n        }\n        return function (zIndex) {\n            if (+zIndex == +zIndex) {\n                f.zIndex = +zIndex;\n            }\n        };\n    };\n    /*\\\n     * eve.f\n     [ method ]\n     **\n     * Returns function that will fire given event with optional arguments.\n     * Arguments that will be passed to the result function will be also\n     * concated to the list of final arguments.\n     | el.onclick = eve.f(\"click\", 1, 2);\n     | eve.on(\"click\", function (a, b, c) {\n     |     console.log(a, b, c); // 1, 2, [event object]\n     | });\n     > Arguments\n     - event (string) event name\n     - varargs (…) and any other arguments\n     = (function) possible event handler function\n    \\*/\n    eve.f = function (event) {\n        var attrs = [].slice.call(arguments, 1);\n        return function () {\n            eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0)));\n        };\n    };\n    /*\\\n     * eve.stop\n     [ method ]\n     **\n     * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing.\n    \\*/\n    eve.stop = function () {\n        stop = 1;\n    };\n    /*\\\n     * eve.nt\n     [ method ]\n     **\n     * Could be used inside event handler to figure out actual name of the event.\n     **\n     > Arguments\n     **\n     - subname (string) #optional subname of the event\n     **\n     = (string) name of the event, if `subname` is not specified\n     * or\n     = (boolean) `true`, if current event’s name contains `subname`\n    \\*/\n    eve.nt = function (subname) {\n        var cur = isArray(current_event) ? current_event.join(\".\") : current_event;\n        if (subname) {\n            return new RegExp(\"(?:\\\\.|\\\\/|^)\" + subname + \"(?:\\\\.|\\\\/|$)\").test(cur);\n        }\n        return cur;\n    };\n    /*\\\n     * eve.nts\n     [ method ]\n     **\n     * Could be used inside event handler to figure out actual name of the event.\n     **\n     **\n     = (array) names of the event\n    \\*/\n    eve.nts = function () {\n        return isArray(current_event) ? current_event : current_event.split(separator);\n    };\n    /*\\\n     * eve.off\n     [ method ]\n     **\n     * Removes given function from the list of event listeners assigned to given name.\n     * If no arguments specified all the events will be cleared.\n     **\n     > Arguments\n     **\n     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n     - f (function) event handler function\n    \\*/\n    /*\\\n     * eve.unbind\n     [ method ]\n     **\n     * See @eve.off\n    \\*/\n    eve.off = eve.unbind = function (name, f) {\n        if (!name) {\n            eve._events = events = {n: {}};\n            return;\n        }\n        var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);\n        if (names.length > 1) {\n            for (var i = 0, ii = names.length; i < ii; i++) {\n                eve.off(names[i], f);\n            }\n            return;\n        }\n        names = isArray(name) ? name : Str(name).split(separator);\n        var e,\n            key,\n            splice,\n            i, ii, j, jj,\n            cur = [events];\n        for (i = 0, ii = names.length; i < ii; i++) {\n            for (j = 0; j < cur.length; j += splice.length - 2) {\n                splice = [j, 1];\n                e = cur[j].n;\n                if (names[i] != wildcard) {\n                    if (e[names[i]]) {\n                        splice.push(e[names[i]]);\n                    }\n                } else {\n                    for (key in e) if (e[has](key)) {\n                        splice.push(e[key]);\n                    }\n                }\n                cur.splice.apply(cur, splice);\n            }\n        }\n        for (i = 0, ii = cur.length; i < ii; i++) {\n            e = cur[i];\n            while (e.n) {\n                if (f) {\n                    if (e.f) {\n                        for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {\n                            e.f.splice(j, 1);\n                            break;\n                        }\n                        !e.f.length && delete e.f;\n                    }\n                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n                        var funcs = e.n[key].f;\n                        for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {\n                            funcs.splice(j, 1);\n                            break;\n                        }\n                        !funcs.length && delete e.n[key].f;\n                    }\n                } else {\n                    delete e.f;\n                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n                        delete e.n[key].f;\n                    }\n                }\n                e = e.n;\n            }\n        }\n    };\n    /*\\\n     * eve.once\n     [ method ]\n     **\n     * Binds given event handler with a given name to only run once then unbind itself.\n     | eve.once(\"login\", f);\n     | eve(\"login\"); // triggers f\n     | eve(\"login\"); // no listeners\n     * Use @eve to trigger the listener.\n     **\n     > Arguments\n     **\n     - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n     - f (function) event handler function\n     **\n     = (function) same return function as @eve.on\n    \\*/\n    eve.once = function (name, f) {\n        var f2 = function () {\n            eve.off(name, f2);\n            return f.apply(this, arguments);\n        };\n        return eve.on(name, f2);\n    };\n    /*\\\n     * eve.version\n     [ property (string) ]\n     **\n     * Current version of the library.\n    \\*/\n    eve.version = version;\n    eve.toString = function () {\n        return \"You are running Eve \" + version;\n    };\n    ( true && module.exports) ? (module.exports = eve) : ( true ? (!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() { return eve; }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))) : (undefined));\n})(this);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZXZlLXJhcGhhZWwvZXZlLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vUmFwaGFlbC8uL25vZGVfbW9kdWxlcy9ldmUtcmFwaGFlbC9ldmUuanM/ZDJiNCJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTMgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vIFxuLy8gaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4vLyBcbi8vIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbi8vIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbi8vIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuLy8gbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4vLyDilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgXFxcXFxuLy8g4pSCIEV2ZSAwLjUuMCAtIEphdmFTY3JpcHQgRXZlbnRzIExpYnJhcnkgICAgICAgICAgICAgICAgICAgICAg4pSCIFxcXFxcbi8vIOKUnOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUpCBcXFxcXG4vLyDilIIgQXV0aG9yIERtaXRyeSBCYXJhbm92c2tpeSAoaHR0cDovL2RtaXRyeS5iYXJhbm92c2tpeS5jb20vKSDilIIgXFxcXFxuLy8g4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYIFxcXFxcblxuKGZ1bmN0aW9uIChnbG9iKSB7XG4gICAgdmFyIHZlcnNpb24gPSBcIjAuNS4wXCIsXG4gICAgICAgIGhhcyA9IFwiaGFzT3duUHJvcGVydHlcIixcbiAgICAgICAgc2VwYXJhdG9yID0gL1tcXC5cXC9dLyxcbiAgICAgICAgY29tYXNlcGFyYXRvciA9IC9cXHMqLFxccyovLFxuICAgICAgICB3aWxkY2FyZCA9IFwiKlwiLFxuICAgICAgICBmdW4gPSBmdW5jdGlvbiAoKSB7fSxcbiAgICAgICAgbnVtc29ydCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gYSAtIGI7XG4gICAgICAgIH0sXG4gICAgICAgIGN1cnJlbnRfZXZlbnQsXG4gICAgICAgIHN0b3AsXG4gICAgICAgIGV2ZW50cyA9IHtuOiB7fX0sXG4gICAgICAgIGZpcnN0RGVmaW5lZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHRoaXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpc1tpXSAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERlZmluZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgaSA9IHRoaXMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKC0taSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpc1tpXSAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgb2JqdG9zID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyxcbiAgICAgICAgU3RyID0gU3RyaW5nLFxuICAgICAgICBpc0FycmF5ID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiAoYXIpIHtcbiAgICAgICAgICAgIHJldHVybiBhciBpbnN0YW5jZW9mIEFycmF5IHx8IG9ianRvcy5jYWxsKGFyKSA9PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZVxuICAgICBbIG1ldGhvZCBdXG5cbiAgICAgKiBGaXJlcyBldmVudCB3aXRoIGdpdmVuIGBuYW1lYCwgZ2l2ZW4gc2NvcGUgYW5kIG90aGVyIHBhcmFtZXRlcnMuXG5cbiAgICAgPiBBcmd1bWVudHNcblxuICAgICAtIG5hbWUgKHN0cmluZykgbmFtZSBvZiB0aGUgKmV2ZW50KiwgZG90IChgLmApIG9yIHNsYXNoIChgL2ApIHNlcGFyYXRlZFxuICAgICAtIHNjb3BlIChvYmplY3QpIGNvbnRleHQgZm9yIHRoZSBldmVudCBoYW5kbGVyc1xuICAgICAtIHZhcmFyZ3MgKC4uLikgdGhlIHJlc3Qgb2YgYXJndW1lbnRzIHdpbGwgYmUgc2VudCB0byBldmVudCBoYW5kbGVyc1xuXG4gICAgID0gKG9iamVjdCkgYXJyYXkgb2YgcmV0dXJuZWQgdmFsdWVzIGZyb20gdGhlIGxpc3RlbmVycy4gQXJyYXkgaGFzIHR3byBtZXRob2RzIGAuZmlyc3REZWZpbmVkKClgIGFuZCBgLmxhc3REZWZpbmVkKClgIHRvIGdldCBmaXJzdCBvciBsYXN0IG5vdCBgdW5kZWZpbmVkYCB2YWx1ZS5cbiAgICBcXCovXG4gICAgICAgIHZhciBldmUgPSBmdW5jdGlvbiAobmFtZSwgc2NvcGUpIHtcbiAgICAgICAgICAgIHZhciBlID0gZXZlbnRzLFxuICAgICAgICAgICAgICAgIG9sZHN0b3AgPSBzdG9wLFxuICAgICAgICAgICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpLFxuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGV2ZS5saXN0ZW5lcnMobmFtZSksXG4gICAgICAgICAgICAgICAgeiA9IDAsXG4gICAgICAgICAgICAgICAgZiA9IGZhbHNlLFxuICAgICAgICAgICAgICAgIGwsXG4gICAgICAgICAgICAgICAgaW5kZXhlZCA9IFtdLFxuICAgICAgICAgICAgICAgIHF1ZXVlID0ge30sXG4gICAgICAgICAgICAgICAgb3V0ID0gW10sXG4gICAgICAgICAgICAgICAgY2UgPSBjdXJyZW50X2V2ZW50LFxuICAgICAgICAgICAgICAgIGVycm9ycyA9IFtdO1xuICAgICAgICAgICAgb3V0LmZpcnN0RGVmaW5lZCA9IGZpcnN0RGVmaW5lZDtcbiAgICAgICAgICAgIG91dC5sYXN0RGVmaW5lZCA9IGxhc3REZWZpbmVkO1xuICAgICAgICAgICAgY3VycmVudF9ldmVudCA9IG5hbWU7XG4gICAgICAgICAgICBzdG9wID0gMDtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBpaTsgaSsrKSBpZiAoXCJ6SW5kZXhcIiBpbiBsaXN0ZW5lcnNbaV0pIHtcbiAgICAgICAgICAgICAgICBpbmRleGVkLnB1c2gobGlzdGVuZXJzW2ldLnpJbmRleCk7XG4gICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS56SW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHF1ZXVlW2xpc3RlbmVyc1tpXS56SW5kZXhdID0gbGlzdGVuZXJzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGluZGV4ZWQuc29ydChudW1zb3J0KTtcbiAgICAgICAgICAgIHdoaWxlIChpbmRleGVkW3pdIDwgMCkge1xuICAgICAgICAgICAgICAgIGwgPSBxdWV1ZVtpbmRleGVkW3orK11dO1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKGwuYXBwbHkoc2NvcGUsIGFyZ3MpKTtcbiAgICAgICAgICAgICAgICBpZiAoc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICBzdG9wID0gb2xkc3RvcDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGwgPSBsaXN0ZW5lcnNbaV07XG4gICAgICAgICAgICAgICAgaWYgKFwiekluZGV4XCIgaW4gbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobC56SW5kZXggPT0gaW5kZXhlZFt6XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0LnB1c2gobC5hcHBseShzY29wZSwgYXJncykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB6Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbCA9IHF1ZXVlW2luZGV4ZWRbel1dO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGwgJiYgb3V0LnB1c2gobC5hcHBseShzY29wZSwgYXJncykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdG9wKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKGwpXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBxdWV1ZVtsLnpJbmRleF0gPSBsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0LnB1c2gobC5hcHBseShzY29wZSwgYXJncykpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdG9wID0gb2xkc3RvcDtcbiAgICAgICAgICAgIGN1cnJlbnRfZXZlbnQgPSBjZTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgICAgIC8vIFVuZG9jdW1lbnRlZC4gRGVidWcgb25seS5cbiAgICAgICAgZXZlLl9ldmVudHMgPSBldmVudHM7XG4gICAgLypcXFxuICAgICAqIGV2ZS5saXN0ZW5lcnNcbiAgICAgWyBtZXRob2QgXVxuXG4gICAgICogSW50ZXJuYWwgbWV0aG9kIHdoaWNoIGdpdmVzIHlvdSBhcnJheSBvZiBhbGwgZXZlbnQgaGFuZGxlcnMgdGhhdCB3aWxsIGJlIHRyaWdnZXJlZCBieSB0aGUgZ2l2ZW4gYG5hbWVgLlxuXG4gICAgID4gQXJndW1lbnRzXG5cbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkXG5cbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIGV2ZW50IGhhbmRsZXJzXG4gICAgXFwqL1xuICAgIGV2ZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgbmFtZXMgPSBpc0FycmF5KG5hbWUpID8gbmFtZSA6IG5hbWUuc3BsaXQoc2VwYXJhdG9yKSxcbiAgICAgICAgICAgIGUgPSBldmVudHMsXG4gICAgICAgICAgICBpdGVtLFxuICAgICAgICAgICAgaXRlbXMsXG4gICAgICAgICAgICBrLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGlpLFxuICAgICAgICAgICAgaixcbiAgICAgICAgICAgIGpqLFxuICAgICAgICAgICAgbmVzLFxuICAgICAgICAgICAgZXMgPSBbZV0sXG4gICAgICAgICAgICBvdXQgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMCwgaWkgPSBuYW1lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBuZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gZXMubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgIGUgPSBlc1tqXS5uO1xuICAgICAgICAgICAgICAgIGl0ZW1zID0gW2VbbmFtZXNbaV1dLCBlW3dpbGRjYXJkXV07XG4gICAgICAgICAgICAgICAgayA9IDI7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGstLSkge1xuICAgICAgICAgICAgICAgICAgICBpdGVtID0gaXRlbXNba107XG4gICAgICAgICAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXMucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9IG91dC5jb25jYXQoaXRlbS5mIHx8IFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVzID0gbmVzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogZXZlLnNlcGFyYXRvclxuICAgICBbIG1ldGhvZCBdXG5cbiAgICAgKiBJZiBmb3Igc29tZSByZWFzb25zIHlvdSBkb27igJl0IGxpa2UgZGVmYXVsdCBzZXBhcmF0b3JzIChgLmAgb3IgYC9gKSB5b3UgY2FuIHNwZWNpZnkgeW91cnNcbiAgICAgKiBoZXJlLiBCZSBhd2FyZSB0aGF0IGlmIHlvdSBwYXNzIGEgc3RyaW5nIGxvbmdlciB0aGFuIG9uZSBjaGFyYWN0ZXIgaXQgd2lsbCBiZSB0cmVhdGVkIGFzXG4gICAgICogYSBsaXN0IG9mIGNoYXJhY3RlcnMuXG5cbiAgICAgLSBzZXBhcmF0b3IgKHN0cmluZykgbmV3IHNlcGFyYXRvci4gRW1wdHkgc3RyaW5nIHJlc2V0cyB0byBkZWZhdWx0OiBgLmAgb3IgYC9gLlxuICAgIFxcKi9cbiAgICBldmUuc2VwYXJhdG9yID0gZnVuY3Rpb24gKHNlcCkge1xuICAgICAgICBpZiAoc2VwKSB7XG4gICAgICAgICAgICBzZXAgPSBTdHIoc2VwKS5yZXBsYWNlKC8oPz1bXFwuXFxeXFxdXFxbXFwtXSkvZywgXCJcXFxcXCIpO1xuICAgICAgICAgICAgc2VwID0gXCJbXCIgKyBzZXAgKyBcIl1cIjtcbiAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlcGFyYXRvciA9IC9bXFwuXFwvXS87XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBldmUub25cbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEJpbmRzIGdpdmVuIGV2ZW50IGhhbmRsZXIgd2l0aCBhIGdpdmVuIG5hbWUuIFlvdSBjYW4gdXNlIHdpbGRjYXJkcyDigJxgKmDigJ0gZm9yIHRoZSBuYW1lczpcbiAgICAgfCBldmUub24oXCIqLnVuZGVyLipcIiwgZik7XG4gICAgIHwgZXZlKFwibW91c2UudW5kZXIuZmxvb3JcIik7IC8vIHRyaWdnZXJzIGZcbiAgICAgKiBVc2UgQGV2ZSB0byB0cmlnZ2VyIHRoZSBsaXN0ZW5lci5cbiAgICAgKipcbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkLCB3aXRoIG9wdGlvbmFsIHdpbGRjYXJkc1xuICAgICAtIGYgKGZ1bmN0aW9uKSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgICoqXG4gICAgIC0gbmFtZSAoYXJyYXkpIGlmIHlvdSBkb27igJl0IHdhbnQgdG8gdXNlIHNlcGFyYXRvcnMsIHlvdSBjYW4gdXNlIGFycmF5IG9mIHN0cmluZ3NcbiAgICAgLSBmIChmdW5jdGlvbikgZXZlbnQgaGFuZGxlciBmdW5jdGlvblxuICAgICAqKlxuICAgICA9IChmdW5jdGlvbikgcmV0dXJuZWQgZnVuY3Rpb24gYWNjZXB0cyBhIHNpbmdsZSBudW1lcmljIHBhcmFtZXRlciB0aGF0IHJlcHJlc2VudHMgei1pbmRleCBvZiB0aGUgaGFuZGxlci4gSXQgaXMgYW4gb3B0aW9uYWwgZmVhdHVyZSBhbmQgb25seSB1c2VkIHdoZW4geW91IG5lZWQgdG8gZW5zdXJlIHRoYXQgc29tZSBzdWJzZXQgb2YgaGFuZGxlcnMgd2lsbCBiZSBpbnZva2VkIGluIGEgZ2l2ZW4gb3JkZXIsIGRlc3BpdGUgb2YgdGhlIG9yZGVyIG9mIGFzc2lnbm1lbnQuIFxuICAgICA+IEV4YW1wbGU6XG4gICAgIHwgZXZlLm9uKFwibW91c2VcIiwgZWF0SXQpKDIpO1xuICAgICB8IGV2ZS5vbihcIm1vdXNlXCIsIHNjcmVhbSk7XG4gICAgIHwgZXZlLm9uKFwibW91c2VcIiwgY2F0Y2hJdCkoMSk7XG4gICAgICogVGhpcyB3aWxsIGVuc3VyZSB0aGF0IGBjYXRjaEl0YCBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBiZWZvcmUgYGVhdEl0YC5cbiAgICAgKlxuICAgICAqIElmIHlvdSB3YW50IHRvIHB1dCB5b3VyIGhhbmRsZXIgYmVmb3JlIG5vbi1pbmRleGVkIGhhbmRsZXJzLCBzcGVjaWZ5IGEgbmVnYXRpdmUgdmFsdWUuXG4gICAgICogTm90ZTogSSBhc3N1bWUgbW9zdCBvZiB0aGUgdGltZSB5b3UgZG9u4oCZdCBuZWVkIHRvIHdvcnJ5IGFib3V0IHotaW5kZXgsIGJ1dCBpdOKAmXMgbmljZSB0byBoYXZlIHRoaXMgZmVhdHVyZSDigJxqdXN0IGluIGNhc2XigJ0uXG4gICAgXFwqL1xuICAgIGV2ZS5vbiA9IGZ1bmN0aW9uIChuYW1lLCBmKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZiAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmFtZXMgPSBpc0FycmF5KG5hbWUpID8gKGlzQXJyYXkobmFtZVswXSkgPyBuYW1lIDogW25hbWVdKSA6IFN0cihuYW1lKS5zcGxpdChjb21hc2VwYXJhdG9yKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5hbWVzID0gaXNBcnJheShuYW1lKSA/IG5hbWUgOiBTdHIobmFtZSkuc3BsaXQoc2VwYXJhdG9yKSxcbiAgICAgICAgICAgICAgICAgICAgZSA9IGV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgZXhpc3Q7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBlID0gZS5uO1xuICAgICAgICAgICAgICAgICAgICBlID0gZS5oYXNPd25Qcm9wZXJ0eShuYW1lc1tpXSkgJiYgZVtuYW1lc1tpXV0gfHwgKGVbbmFtZXNbaV1dID0ge246IHt9fSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGUuZiA9IGUuZiB8fCBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGUuZi5sZW5ndGg7IGkgPCBpaTsgaSsrKSBpZiAoZS5mW2ldID09IGYpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhpc3QgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgIWV4aXN0ICYmIGUuZi5wdXNoKGYpO1xuICAgICAgICAgICAgfShuYW1lc1tpXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoekluZGV4KSB7XG4gICAgICAgICAgICBpZiAoK3pJbmRleCA9PSArekluZGV4KSB7XG4gICAgICAgICAgICAgICAgZi56SW5kZXggPSArekluZGV4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5mXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIGZ1bmN0aW9uIHRoYXQgd2lsbCBmaXJlIGdpdmVuIGV2ZW50IHdpdGggb3B0aW9uYWwgYXJndW1lbnRzLlxuICAgICAqIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIHRvIHRoZSByZXN1bHQgZnVuY3Rpb24gd2lsbCBiZSBhbHNvXG4gICAgICogY29uY2F0ZWQgdG8gdGhlIGxpc3Qgb2YgZmluYWwgYXJndW1lbnRzLlxuICAgICB8IGVsLm9uY2xpY2sgPSBldmUuZihcImNsaWNrXCIsIDEsIDIpO1xuICAgICB8IGV2ZS5vbihcImNsaWNrXCIsIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgIHwgICAgIGNvbnNvbGUubG9nKGEsIGIsIGMpOyAvLyAxLCAyLCBbZXZlbnQgb2JqZWN0XVxuICAgICB8IH0pO1xuICAgICA+IEFyZ3VtZW50c1xuICAgICAtIGV2ZW50IChzdHJpbmcpIGV2ZW50IG5hbWVcbiAgICAgLSB2YXJhcmdzICjigKYpIGFuZCBhbnkgb3RoZXIgYXJndW1lbnRzXG4gICAgID0gKGZ1bmN0aW9uKSBwb3NzaWJsZSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgXFwqL1xuICAgIGV2ZS5mID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBhdHRycyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV2ZS5hcHBseShudWxsLCBbZXZlbnQsIG51bGxdLmNvbmNhdChhdHRycykuY29uY2F0KFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKSkpO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5zdG9wXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJcyB1c2VkIGluc2lkZSBhbiBldmVudCBoYW5kbGVyIHRvIHN0b3AgdGhlIGV2ZW50LCBwcmV2ZW50aW5nIGFueSBzdWJzZXF1ZW50IGxpc3RlbmVycyBmcm9tIGZpcmluZy5cbiAgICBcXCovXG4gICAgZXZlLnN0b3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHN0b3AgPSAxO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5udFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ291bGQgYmUgdXNlZCBpbnNpZGUgZXZlbnQgaGFuZGxlciB0byBmaWd1cmUgb3V0IGFjdHVhbCBuYW1lIG9mIHRoZSBldmVudC5cbiAgICAgKipcbiAgICAgPiBBcmd1bWVudHNcbiAgICAgKipcbiAgICAgLSBzdWJuYW1lIChzdHJpbmcpICNvcHRpb25hbCBzdWJuYW1lIG9mIHRoZSBldmVudFxuICAgICAqKlxuICAgICA9IChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBpZiBgc3VibmFtZWAgaXMgbm90IHNwZWNpZmllZFxuICAgICAqIG9yXG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCwgaWYgY3VycmVudCBldmVudOKAmXMgbmFtZSBjb250YWlucyBgc3VibmFtZWBcbiAgICBcXCovXG4gICAgZXZlLm50ID0gZnVuY3Rpb24gKHN1Ym5hbWUpIHtcbiAgICAgICAgdmFyIGN1ciA9IGlzQXJyYXkoY3VycmVudF9ldmVudCkgPyBjdXJyZW50X2V2ZW50LmpvaW4oXCIuXCIpIDogY3VycmVudF9ldmVudDtcbiAgICAgICAgaWYgKHN1Ym5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKD86XFxcXC58XFxcXC98XilcIiArIHN1Ym5hbWUgKyBcIig/OlxcXFwufFxcXFwvfCQpXCIpLnRlc3QoY3VyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3VyO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5udHNcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENvdWxkIGJlIHVzZWQgaW5zaWRlIGV2ZW50IGhhbmRsZXIgdG8gZmlndXJlIG91dCBhY3R1YWwgbmFtZSBvZiB0aGUgZXZlbnQuXG4gICAgICoqXG4gICAgICoqXG4gICAgID0gKGFycmF5KSBuYW1lcyBvZiB0aGUgZXZlbnRcbiAgICBcXCovXG4gICAgZXZlLm50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkoY3VycmVudF9ldmVudCkgPyBjdXJyZW50X2V2ZW50IDogY3VycmVudF9ldmVudC5zcGxpdChzZXBhcmF0b3IpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5vZmZcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZ2l2ZW4gZnVuY3Rpb24gZnJvbSB0aGUgbGlzdCBvZiBldmVudCBsaXN0ZW5lcnMgYXNzaWduZWQgdG8gZ2l2ZW4gbmFtZS5cbiAgICAgKiBJZiBubyBhcmd1bWVudHMgc3BlY2lmaWVkIGFsbCB0aGUgZXZlbnRzIHdpbGwgYmUgY2xlYXJlZC5cbiAgICAgKipcbiAgICAgPiBBcmd1bWVudHNcbiAgICAgKipcbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkLCB3aXRoIG9wdGlvbmFsIHdpbGRjYXJkc1xuICAgICAtIGYgKGZ1bmN0aW9uKSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBldmUudW5iaW5kXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBTZWUgQGV2ZS5vZmZcbiAgICBcXCovXG4gICAgZXZlLm9mZiA9IGV2ZS51bmJpbmQgPSBmdW5jdGlvbiAobmFtZSwgZikge1xuICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIGV2ZS5fZXZlbnRzID0gZXZlbnRzID0ge246IHt9fTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmFtZXMgPSBpc0FycmF5KG5hbWUpID8gKGlzQXJyYXkobmFtZVswXSkgPyBuYW1lIDogW25hbWVdKSA6IFN0cihuYW1lKS5zcGxpdChjb21hc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKG5hbWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG5hbWVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBldmUub2ZmKG5hbWVzW2ldLCBmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBuYW1lcyA9IGlzQXJyYXkobmFtZSkgPyBuYW1lIDogU3RyKG5hbWUpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIHZhciBlLFxuICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgc3BsaWNlLFxuICAgICAgICAgICAgaSwgaWksIGosIGpqLFxuICAgICAgICAgICAgY3VyID0gW2V2ZW50c107XG4gICAgICAgIGZvciAoaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGN1ci5sZW5ndGg7IGogKz0gc3BsaWNlLmxlbmd0aCAtIDIpIHtcbiAgICAgICAgICAgICAgICBzcGxpY2UgPSBbaiwgMV07XG4gICAgICAgICAgICAgICAgZSA9IGN1cltqXS5uO1xuICAgICAgICAgICAgICAgIGlmIChuYW1lc1tpXSAhPSB3aWxkY2FyZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZVtuYW1lc1tpXV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwbGljZS5wdXNoKGVbbmFtZXNbaV1dKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIGUpIGlmIChlW2hhc10oa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3BsaWNlLnB1c2goZVtrZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdXIuc3BsaWNlLmFwcGx5KGN1ciwgc3BsaWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGN1ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBlID0gY3VyW2ldO1xuICAgICAgICAgICAgd2hpbGUgKGUubikge1xuICAgICAgICAgICAgICAgIGlmIChmKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gZS5mLmxlbmd0aDsgaiA8IGpqOyBqKyspIGlmIChlLmZbal0gPT0gZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuZi5zcGxpY2UoaiwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAhZS5mLmxlbmd0aCAmJiBkZWxldGUgZS5mO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIGUubikgaWYgKGUubltoYXNdKGtleSkgJiYgZS5uW2tleV0uZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZ1bmNzID0gZS5uW2tleV0uZjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gZnVuY3MubGVuZ3RoOyBqIDwgamo7IGorKykgaWYgKGZ1bmNzW2pdID09IGYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jcy5zcGxpY2UoaiwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAhZnVuY3MubGVuZ3RoICYmIGRlbGV0ZSBlLm5ba2V5XS5mO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGUuZjtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChrZXkgaW4gZS5uKSBpZiAoZS5uW2hhc10oa2V5KSAmJiBlLm5ba2V5XS5mKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgZS5uW2tleV0uZjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlID0gZS5uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogZXZlLm9uY2VcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEJpbmRzIGdpdmVuIGV2ZW50IGhhbmRsZXIgd2l0aCBhIGdpdmVuIG5hbWUgdG8gb25seSBydW4gb25jZSB0aGVuIHVuYmluZCBpdHNlbGYuXG4gICAgIHwgZXZlLm9uY2UoXCJsb2dpblwiLCBmKTtcbiAgICAgfCBldmUoXCJsb2dpblwiKTsgLy8gdHJpZ2dlcnMgZlxuICAgICB8IGV2ZShcImxvZ2luXCIpOyAvLyBubyBsaXN0ZW5lcnNcbiAgICAgKiBVc2UgQGV2ZSB0byB0cmlnZ2VyIHRoZSBsaXN0ZW5lci5cbiAgICAgKipcbiAgICAgPiBBcmd1bWVudHNcbiAgICAgKipcbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkLCB3aXRoIG9wdGlvbmFsIHdpbGRjYXJkc1xuICAgICAtIGYgKGZ1bmN0aW9uKSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgICoqXG4gICAgID0gKGZ1bmN0aW9uKSBzYW1lIHJldHVybiBmdW5jdGlvbiBhcyBAZXZlLm9uXG4gICAgXFwqL1xuICAgIGV2ZS5vbmNlID0gZnVuY3Rpb24gKG5hbWUsIGYpIHtcbiAgICAgICAgdmFyIGYyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXZlLm9mZihuYW1lLCBmMik7XG4gICAgICAgICAgICByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gZXZlLm9uKG5hbWUsIGYyKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBldmUudmVyc2lvblxuICAgICBbIHByb3BlcnR5IChzdHJpbmcpIF1cbiAgICAgKipcbiAgICAgKiBDdXJyZW50IHZlcnNpb24gb2YgdGhlIGxpYnJhcnkuXG4gICAgXFwqL1xuICAgIGV2ZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICBldmUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIllvdSBhcmUgcnVubmluZyBFdmUgXCIgKyB2ZXJzaW9uO1xuICAgIH07XG4gICAgKHR5cGVvZiBtb2R1bGUgIT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cykgPyAobW9kdWxlLmV4cG9ydHMgPSBldmUpIDogKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kID8gKGRlZmluZShcImV2ZVwiLCBbXSwgZnVuY3Rpb24oKSB7IHJldHVybiBldmU7IH0pKSA6IChnbG9iLmV2ZSA9IGV2ZSkpO1xufSkodGhpcyk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/eve-raphael/eve.js\n");
57624
57625/***/ })
57625
57626
57627/******/ });
57628});
57629/* @license
57630morris.js v0.5.0
57631Copyright 2014 Olly Smith All rights reserved.
57632Licensed under the BSD-2-Clause License.
57633*/
57634
57635
57636(function() {
57637  var $, Morris, minutesSpecHelper, secondsSpecHelper,
57638    __slice = [].slice,
57639    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
57640    __hasProp = {}.hasOwnProperty,
57641    __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; },
57642    __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; };
57643
57644  Morris = window.Morris = {};
57645
57646  $ = jQuery;
57647
57648  Morris.EventEmitter = (function() {
57649    function EventEmitter() {}
57650
57651    EventEmitter.prototype.on = function(name, handler) {
57652      if (this.handlers == null) {
57653        this.handlers = {};
57654      }
57655      if (this.handlers[name] == null) {
57656        this.handlers[name] = [];
57657      }
57658      this.handlers[name].push(handler);
57659      return this;
57660    };
57661
57662    EventEmitter.prototype.fire = function() {
57663      var args, handler, name, _i, _len, _ref, _results;
57664      name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
57665      if ((this.handlers != null) && (this.handlers[name] != null)) {
57666        _ref = this.handlers[name];
57667        _results = [];
57668        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
57669          handler = _ref[_i];
57670          _results.push(handler.apply(null, args));
57671        }
57672        return _results;
57673      }
57674    };
57675
57676    return EventEmitter;
57677
57678  })();
57679
57680  Morris.commas = function(num) {
57681    var absnum, intnum, ret, strabsnum;
57682    if (num != null) {
57683      ret = num < 0 ? "-" : "";
57684      absnum = Math.abs(num);
57685      intnum = Math.floor(absnum).toFixed(0);
57686      ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
57687      strabsnum = absnum.toString();
57688      if (strabsnum.length > intnum.length) {
57689        ret += strabsnum.slice(intnum.length);
57690      }
57691      return ret;
57692    } else {
57693      return '-';
57694    }
57695  };
57696
57697  Morris.pad2 = function(number) {
57698    return (number < 10 ? '0' : '') + number;
57699  };
57700
57701  Morris.Grid = (function(_super) {
57702    __extends(Grid, _super);
57703
57704    function Grid(options) {
57705      this.resizeHandler = __bind(this.resizeHandler, this);
57706      var _this = this;
57707      if (typeof options.element === 'string') {
57708        this.el = $(document.getElementById(options.element));
57709      } else {
57710        this.el = $(options.element);
57711      }
57712      if ((this.el == null) || this.el.length === 0) {
57713        throw new Error("Graph container element not found");
57714      }
57715      if (this.el.css('position') === 'static') {
57716        this.el.css('position', 'relative');
57717      }
57718      this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options);
57719      if (typeof this.options.units === 'string') {
57720        this.options.postUnits = options.units;
57721      }
57722      this.raphael = new Raphael(this.el[0]);
57723      this.elementWidth = null;
57724      this.elementHeight = null;
57725      this.dirty = false;
57726      this.selectFrom = null;
57727      if (this.init) {
57728        this.init();
57729      }
57730      this.setData(this.options.data);
57731      this.el.bind('mousemove', function(evt) {
57732        var left, offset, right, width, x;
57733        offset = _this.el.offset();
57734        x = evt.pageX - offset.left;
57735        if (_this.selectFrom) {
57736          left = _this.data[_this.hitTest(Math.min(x, _this.selectFrom))]._x;
57737          right = _this.data[_this.hitTest(Math.max(x, _this.selectFrom))]._x;
57738          width = right - left;
57739          return _this.selectionRect.attr({
57740            x: left,
57741            width: width
57742          });
57743        } else {
57744          return _this.fire('hovermove', x, evt.pageY - offset.top);
57745        }
57746      });
57747      this.el.bind('mouseleave', function(evt) {
57748        if (_this.selectFrom) {
57749          _this.selectionRect.hide();
57750          _this.selectFrom = null;
57751        }
57752        return _this.fire('hoverout');
57753      });
57754      this.el.bind('touchstart touchmove touchend', function(evt) {
57755        var offset, touch;
57756        touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
57757        offset = _this.el.offset();
57758        return _this.fire('hovermove', touch.pageX - offset.left, touch.pageY - offset.top);
57759      });
57760      this.el.bind('click', function(evt) {
57761        var offset;
57762        offset = _this.el.offset();
57763        return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top);
57764      });
57765      if (this.options.rangeSelect) {
57766        this.selectionRect = this.raphael.rect(0, 0, 0, this.el.innerHe
57766ight()).attr({
57767          fill: this.options.rangeSelectColor,
57768          stroke: false
57769        }).toBack().hide();
57770        this.el.bind('mousedown', function(evt) {
57771          var offset;
57772          offset = _this.el.offset();
57773          return _this.startRange(evt.pageX - offset.left);
57774        });
57775        this.el.bind('mouseup', function(evt) {
57776          var offset;
57777          offset = _this.el.offset();
57778          _this.endRange(evt.pageX - offset.left);
57779          return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top);
57780        });
57781      }
57782      if (this.options.resize) {
57783        $(window).bind('resize', function(evt) {
57784          if (_this.timeoutId != null) {
57785            window.clearTimeout(_this.timeoutId);
57786          }
57787          return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);
57788        });
57789      }
57790      this.el.css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
57791      if (this.postInit) {
57792        this.postInit();
57793      }
57794    }
57795
57796    Grid.prototype.gridDefaults = {
57797      dateFormat: null,
57798      axes: true,
57799      grid: true,
57800      gridLineColor: '#aaa',
57801      gridStrokeWidth: 0.5,
57802      gridTextColor: '#888',
57803      gridTextSize: 12,
57804      gridTextFamily: 'sans-serif',
57805      gridTextWeight: 'normal',
57806      hideHover: false,
57807      yLabelFormat: null,
57808      xLabelAngle: 0,
57809      numLines: 5,
57810      padding: 25,
57811      parseTime: true,
57812      postUnits: '',
57813      preUnits: '',
57814      ymax: 'auto',
57815      ymin: 'auto 0',
57816      goals: [],
57817      goalStrokeWidth: 1.0,
57818      goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'],
57819      events: [],
57820      eventStrokeWidth: 1.0,
57821      eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'],
57822      rangeSelect: null,
57823      rangeSelectColor: '#eef',
57824      resize: false
57825    };
57826
57827    Grid.prototype.setData = function(data, redraw) {
57828      var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval, _ref;
57829      if (redraw == null) {
57830        redraw = true;
57831      }
57832      this.options.data = data;
57833      if ((data == null) || data.length === 0) {
57834        this.data = [];
57835        this.raphael.clear();
57836        if (this.hover != null) {
57837          this.hover.hide();
57838        }
57839        return;
57840      }
57841      ymax = this.cumulative ? 0 : null;
57842      ymin = this.cumulative ? 0 : null;
57843      if (this.options.goals.length > 0) {
57844        minGoal = Math.min.apply(Math, this.options.goals);
57845        maxGoal = Math.max.apply(Math, this.options.goals);
57846        ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal;
57847        ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal;
57848      }
57849      this.data = (function() {
57850        var _i, _len, _results;
57851        _results = [];
57852        for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) {
57853          row = data[index];
57854          ret = {
57855            src: row
57856          };
57857          ret.label = row[this.options.xkey];
57858          if (this.options.parseTime) {
57859            ret.x = Morris.parseDate(ret.label);
57860            if (this.options.dateFormat) {
57861              ret.label = this.options.dateFormat(ret.x);
57862            } else if (typeof ret.label === 'number') {
57863              ret.label = new Date(ret.label).toString();
57864            }
57865          } else {
57866            ret.x = index;
57867            if (this.options.xLabelFormat) {
57868              ret.label = this.options.xLabelFormat(ret);
57869            }
57870          }
57871          total = 0;
57872          ret.y = (function() {
57873            var _j, _len1, _ref, _results1;
57874            _ref = this.options.ykeys;
57875            _results1 = [];
57876            for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) {
57877              ykey = _ref[idx];
57878              yval = row[ykey];
57879              if (typeof yval === 'string') {
57880                yval = parseFloat(yval);
57881              }
57882              if ((yval != null) && typeof yval !== 'number') {
57883                yval = null;
57884              }
57885              if (yval != null) {
57886                if (this.cumulative) {
57887                  total += yval;
57888                } else {
57889                  if (ymax != null) {
57890                    ymax = Math.max(yval, ymax);
57891                    ymin = Math.min(yval, ymin);
57892                  } else {
57893                    ymax = ymin = yval;
57894                  }
57895                }
57896              }
57897              if (this.cumulative && (total != null)) {
57898                ymax = Math.max(total, ymax);
57899                ymin = Math.min(total, ymin);
57900              }
57901              _results1.push(yval);
57902            }
57903            return _results1;
57904          }).call(this);
57905          _results.push(ret);
57906        }
57907        return _results;
57908      }).call(this);
57909      if (this.options.parseTime) {
57910        this.data = this.data.sort(function(a, b) {
57911          return (a.x > b.x) - (b.x > a.x);
57912        });
57913      }
57914      this.xmin = this.data[0].x;
57915      this.xmax = this.data[this.data.length - 1].x;
57916      this.events = [];
57917      if (this.options.events.length > 0) {
57918        if (this.options.parseTime) {
57919          this.events = (function() {
57920            var _i, _len, _ref, _results;
57921            _ref = this.options.events;
57922            _results = [];
57923            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
57924              e = _ref[_i];
57925              _results.push(Morris.parseDate(e));
57926            }
57927            return _results;
57928          }).call(this);
57929        } else {
57930          this.events = this.options.events;
57931        }
57932        this.xmax = Math.max(this.xmax, Math.max.apply(Math, this.events));
57933        this.xmin = Math.min(this.xmin, Math.min.apply(Math, this.events));
57934      }
57935      if (this.xmin === this.xmax) {
57936        this.xmin -= 1;
57937        this.xmax += 1;
57938      }
57939      this.ymin = this.yboundary('min', ymin);
57940      this.ymax = this.yboundary('max', ymax);
57941      if (this.ymin === this.ymax) {
57942        if (ymin) {
57943          this.ymin -= 1;
57944        }
57945        this.ymax += 1;
57946      }
57947      if (((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') || this.options.grid === true) {
57948        if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) {
57949          this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines);
57950          this.ymin = Math.min(this.ymin, this.grid[0]);
57951          this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]);
57952        } else {
57953          step = (this.ymax - this.ymin) / (this.options.numLines - 1);
57954          this.grid = (function() {
57955            var _i, _ref1, _ref2, _results;
57956            _results = [];
57957            for (y = _i = _ref1 = this.ymin, _ref2 = this.ymax; step > 0 ? _i <= _ref2 : _i >= _ref2; y = _i += step) {
57958              _results.push(y);
57959            }
57960            return _results;
57961          }).call(this);
57962        }
57963      }
57964      this.dirty = true;
57965      if (redraw) {
57966        return this.redraw();
57967      }
57968    };
57969
57970    Grid.prototype.yboundary = function(boundaryType, currentValue) {
57971      var boundaryOption, suggestedValue;
57972      boundaryOption = this.options["y" + boundaryType];
57973      if (typeof boundaryOption === 'string') {
57974        if (boundaryOption.slice(0, 4) === 'auto') {
57975          if (boundaryOption.length > 5) {
57976            suggestedValue = parseInt(boundaryOption.slice(5), 10);
57977            if (currentValue == null) {
57978              return suggestedValue;
57979            }
57980            return Math[boundaryType](currentValue, suggestedValue);
57981          } else {
57982            if (currentValue != null) {
57983              return currentValue;
57984            } else {
57985              return 0;
57986            }
57987          }
57988        } else {
57989          return parseInt(boundaryOption, 10);
57990        }
57991      } else {
57992        return boundaryOption;
57993      }
57994    };
57995
57996    Grid.prototype.autoGridLines = function(ymin, ymax, nlines) {
57997      var gmax, gmin, grid, smag, span, step, unit, y, ymag;
57998      span = ymax - ymin;
57999      ymag = Math.floor(Math.log(span) / Math.log(10));
58000      unit = Math.pow(10, ymag);
58001      gmin = Math.floor(ymin / unit) * unit;
58002      gmax = Math.ceil(ymax / unit) * unit;
58003      step = (gmax - gmin) / (nlines - 1);
58004      if (unit === 1 && step > 1 && Math.ceil(step) !== step) {
58005        step = Math.ceil(step);
58006        gmax = gmin + step * (nlines - 1);
58007      }
58008      if (gmin < 0 && gmax > 0) {
58009        gmin = Math.floor(ymin / step) * step;
58010        gmax = Math.ceil(ymax / step) * step;
58011      }
58012      if (step < 1) {
58013        smag = Math.floor(Math.log(step) / Math.log(10));
58014        grid = (function() {
58015          var _i, _results;
58016          _results = [];
58017          for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) {
58018            _results.push(parseFloat(y.toFixed(1 - smag)));
58019          }
58020          return _results;
58021        })();
58022      } else {
58023        grid = (function() {
58024          var _i, _results;
58025          _results = [];
58026          for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) {
58027            _results.push(y);
58028          }
58029          return _results;
58030        })();
58031      }
58032      return grid;
58033    };
58034
58035    Grid.prototype._calc = function() {
58036      var bottomOffsets, gridLine, h, i, w, yLabelWidths, _ref, _ref1;
58037      w = this.el.width();
58038      h = this.el.height();
58039      if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) {
58040        this.elementWidth = w;
58041        this.elementHeight = h;
58042        this.dirty = false;
58043        this.left = this.options.padding;
58044        this.right = this.elementWidth - this.options.padding;
58045        this.top = this.options.padding;
58046        this.bottom = this.elementHeight - this.options.padding;
58047        if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') {
58048          yLabelWidths = (function() {
58049            var _i, _len, _ref1, _results;
58050            _ref1 = this.grid;
58051            _results = [];
58052            for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
58053              gridLine = _ref1[_i];
58054              _results.push(this.measureText(this.yAxisFormat(gridLine)).width);
58055            }
58056            return _results;
58057          }).call(this);
58058          this.left += Math.max.apply(Math, yLabelWidths);
58059        }
58060        if ((_ref1 = this.options.axes) === true || _ref1 === 'both' || _ref1 === 'x') {
58061          bottomOffsets = (function() {
58062            var _i, _ref2, _results;
58063            _results = [];
58064            for (i = _i = 0, _ref2 = this.data.length; 0 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 0 <= _ref2 ? ++_i : --_i) {
58065              _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height);
58066            }
58067            return _results;
58068          }).call(this);
58069          this.bottom -= Math.max.apply(Math, bottomOffsets);
58070        }
58071        this.width = Math.max(1, this.right - this.left);
58072        this.height = Math.max(1, this.bottom - this.top);
58073        this.dx = this.width / (this.xmax - this.xmin);
58074        this.dy = this.height / (this.ymax - this.ymin);
58075        if (this.calc) {
58076          return this.calc();
58077        }
58078      }
58079    };
58080
58081    Grid.prototype.transY = function(y) {
58082      return this.bottom - (y - this.ymin) * this.dy;
58083    };
58084
58085    Grid.prototype.transX = function(x) {
58086      if (this.data.length === 1) {
58087        return (this.left + this.right) / 2;
58088      } else {
58089        return this.left + (x - this.xmin) * this.dx;
58090      }
58091    };
58092
58093    Grid.prototype.redraw = function() {
58094      this.raphael.clear();
58095      this._calc();
58096      this.drawGrid();
58097      this.drawGoals();
58098      this.drawEvents();
58099      if (this.draw) {
58100        return this.draw();
58101      }
58102    };
58103
58104    Grid.prototype.measureText = function(text, angle) {
58105      var ret, tt;
58106      if (angle == null) {
58107        angle = 0;
58108      }
58109      tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle);
58110      ret = tt.getBBox();
58111      tt.remove();
58112      return ret;
58113    };
58114
58115    Grid.prototype.yAxisFormat = function(label) {
58116      return this.yLabelFormat(label);
58117    };
58118
58119    Grid.prototype.yLabelFormat = function(label) {
58120      if (typeof this.options.yLabelFormat === 'function') {
58121        return this.options.yLabelFormat(label);
58122      } else {
58123        return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits;
58124      }
58125    };
58126
58127    Grid.prototype.drawGrid = function() {
58128      var lineY, y, _i, _len, _ref, _ref1, _ref2, _results;
58129      if (this.options.grid === false && ((_ref = this.options.axes) !== true && _ref !== 'both' && _ref !== 'y')) {
58130        return;
58131      }
58132      _ref1 = this.grid;
58133      _results = [];
58134      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
58135        lineY = _ref1[_i];
58136        y = this.transY(lineY);
58137        if ((_ref2 = this.options.axes) === true || _ref2 === 'both' || _ref2 === 'y') {
58138          this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY));
58139        }
58140        if (this.options.grid) {
58141          _results.push(this.drawGridLine("M" + this.left + "," + y + "H" + (this.left + this.width)));
58142        } else {
58143          _results.push(void 0);
58144        }
58145      }
58146      return _results;
58147    };
58148
58149    Grid.prototype.drawGoals = function() {
58150      var color, goal, i, _i, _len, _ref, _results;
58151      _ref = this.options.goals;
58152      _results = [];
58153      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
58154        goal = _ref[i];
58155        color = this.options.goalLineColors[i % this.options.goalLineColors.length];
58156        _results.push(this.drawGoal(goal, color));
58157      }
58158      return _results;
58159    };
58160
58161    Grid.prototype.drawEvents = function() {
58162      var color, event, i, _i, _len, _ref, _results;
58163      _ref = this.events;
58164      _results = [];
58165      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
58166        event = _ref[i];
58167        color = this.options.eventLineColors[i % this.options.eventLineColors.length];
58168        _results.push(this.drawEvent(event, color));
58169      }
58170      return _results;
58171    };
58172
58173    Grid.prototype.drawGoal = function(goal, color) {
58174      return this.raphael.path("M" + this.left + "," + (this.transY(goal)) + "H" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth);
58175    };
58176
58177    Grid.prototype.drawEvent = function(event, color) {
58178      return this.raphael.path("M" + (this.transX(event)) + "," + this.bottom + "V" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth);
58179    };
58180
58181    Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) {
58182      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');
58183    };
58184
58185    Grid.prototype.drawGridLine = function(path) {
58186      return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
58187    };
58188
58189    Grid.prototype.startRange = function(x) {
58190      this.hover.hide();
58191      this.selectFrom = x;
58192      return this.selectionRect.attr({
58193        x: x,
58194        width: 0
58195      }).show();
58196    };
58197
58198    Grid.prototype.endRange = function(x) {
58199      var end, start;
58200      if (this.selectFrom) {
58201        start = Math.min(this.selectFrom, x);
58202        end = Math.max(this.selectFrom, x);
58203        this.options.rangeSelect.call(this.el, {
58204          start: this.data[this.hitTest(start)].x,
58205          end: this.data[this.hitTest(end)].x
58206        });
58207        return this.selectFrom = null;
58208      }
58209    };
58210
58211    Grid.prototype.resizeHandler = function() {
58212      this.timeoutId = null;
58213      this.raphael.setSize(this.el.width(), this.el.height());
58214      return this.redraw();
58215    };
58216
58217    return Grid;
58218
58219  })(Morris.EventEmitter);
58220
58221  Morris.parseDate = function(date) {
58222    var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs;
58223    if (typeof date === 'number') {
58224      return date;
58225    }
58226    m = date.match(/^(\d+) Q(\d)$/);
58227    n = date.match(/^(\d+)-(\d+)$/);
58228    o = date.match(/^(\d+)-(\d+)-(\d+)$/);
58229    p = date.match(/^(\d+) W(\d+)$/);
58230    q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/);
58231    r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/);
58232    if (m) {
58233      return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime();
58234    } else if (n) {
58235      return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime();
58236    } else if (o) {
58237      return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime();
58238    } else if (p) {
58239      ret = new Date(parseInt(p[1], 10), 0, 1);
58240      if (ret.getDay() !== 4) {
58241        ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7);
58242      }
58243      return ret.getTime() + parseInt(p[2], 10) * 604800000;
58244    } else if (q) {
58245      if (!q[6]) {
58246        return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime();
58247      } else {
58248        offsetmins = 0;
58249        if (q[6] !== 'Z') {
58250          offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10);
58251          if (q[7] === '+') {
58252            offsetmins = 0 - offsetmins;
58253          }
58254        }
58255        return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins);
58256      }
58257    } else if (r) {
58258      secs = parseFloat(r[6]);
58259      isecs = Math.floor(secs);
58260      msecs = Math.round((secs - isecs) * 1000);
58261      if (!r[8]) {
58262        return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime();
58263      } else {
58264        offsetmins = 0;
58265        if (r[8] !== 'Z') {
58266          offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10);
58267          if (r[9] === '+') {
58268            offsetmins = 0 - offsetmins;
58269          }
58270        }
58271        return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs);
58272      }
58273    } else {
58274      return new Date(parseInt(date, 10), 0, 1).getTime();
58275    }
58276  };
58277
58278  Morris.Hover = (function() {
58279    Hover.defaults = {
58280      "class": 'morris-hover morris-default-style'
58281    };
58282
58283    function Hover(options) {
58284      if (options == null) {
58285        options = {};
58286      }
58287      this.options = $.extend({}, Morris.Hover.defaults, options);
58288      this.el = $("<div class='" + this.options["class"] + "'></div>");
58289      this.el.hide();
58290      this.options.parent.append(this.el);
58291    }
58292
58293    Hover.prototype.update = function(html, x, y) {
58294      if (!html) {
58295        return this.hide();
58296      } else {
58297        this.html(html);
58298        this.show();
58299        return this.moveTo(x, y);
58300      }
58301    };
58302
58303    Hover.prototype.html = function(content) {
58304      return this.el.html(content);
58305    };
58306
58307    Hover.prototype.moveTo = function(x, y) {
58308      var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top;
58309      parentWidth = this.options.parent.innerWidth();
58310      parentHeight = this.options.parent.innerHeight();
58311      hoverWidth = this.el.outerWidth();
58312      hoverHeight = this.el.outerHeight();
58313      left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth);
58314      if (y != null) {
58315        top = y - hoverHeight - 10;
58316        if (top < 0) {
58317          top = y + 10;
58318          if (top + hoverHeight > parentHeight) {
58319            top = parentHeight / 2 - hoverHeight / 2;
58320          }
58321        }
58322      } else {
58323        top = parentHeight / 2 - hoverHeight / 2;
58324      }
58325      return this.el.css({
58326        left: left + "px",
58327        top: parseInt(top) + "px"
58328      });
58329    };
58330
58331    Hover.prototype.show = function() {
58332      return this.el.show();
58333    };
58334
58335    Hover.prototype.hide = function() {
58336      return this.el.hide();
58337    };
58338
58339    return Hover;
58340
58341  })();
58342
58343  Morris.Line = (function(_super) {
58344    __extends(Line, _super);
58345
58346    function Line(options) {
58347      this.hilight = __bind(this.hilight, this);
58348      this.onHoverOut = __bind(this.onHoverOut, this);
58349      this.onHoverMove = __bind(this.onHoverMove, this);
58350      this.onGridClick = __bind(this.onGridClick, this);
58351      if (!(this instanceof Morris.Line)) {
58352        return new Morris.Line(options);
58353      }
58354      Line.__super__.constructor.call(this, options);
58355    }
58356
58357    Line.prototype.init = function() {
58358      if (this.options.hideHover !== 'always') {
58359        this.hover = new Morris.Hover({
58360          parent: this.el
58361        });
58362        this.on('hovermove', this.onHoverMove);
58363        this.on('hoverout', this.onHoverOut);
58364        return this.on('gridclick', this.onGridClick);
58365      }
58366    };
58367
58368    Line.prototype.defaults = {
58369      lineWidth: 3,
58370      pointSize: 4,
58371      lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
58372      pointStrokeWidths: [1],
58373      pointStrokeColors: ['#ffffff'],
58374      pointFillColors: [],
58375      smooth: true,
58376      xLabels: 'auto',
58377      xLabelFormat: null,
58378      xLabelMargin: 24,
58379      hideHover: false
58380    };
58381
58382    Line.prototype.calc = function() {
58383      this.calcPoints();
58384      return this.generatePaths();
58385    };
58386
58387    Line.prototype.calcPoints = function() {
58388      var row, y, _i, _len, _ref, _results;
58389      _ref = this.data;
58390      _results = [];
58391      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
58392        row = _ref[_i];
58393        row._x = this.transX(row.x);
58394        row._y = (function() {
58395          var _j, _len1, _ref1, _results1;
58396          _ref1 = row.y;
58397          _results1 = [];
58398          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
58399            y = _ref1[_j];
58400            if (y != null) {
58401              _results1.push(this.transY(y));
58402            } else {
58403              _results1.push(y);
58404            }
58405          }
58406          return _results1;
58407        }).call(this);
58408        _results.push(row._ymax = Math.min.apply(Math, [this.bottom].concat((function() {
58409          var _j, _len1, _ref1, _results1;
58410          _ref1 = row._y;
58411          _results1 = [];
58412          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
58413            y = _ref1[_j];
58414            if (y != null) {
58415              _results1.push(y);
58416            }
58417          }
58418          return _results1;
58419        })())));
58420      }
58421      return _results;
58422    };
58423
58424    Line.prototype.hitTest = function(x) {
58425      var index, r, _i, _len, _ref;
58426      if (this.data.length === 0) {
58427        return null;
58428      }
58429      _ref = this.data.slice(1);
58430      for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
58431        r = _ref[index];
58432        if (x < (r._x + this.data[index]._x) / 2) {
58433          break;
58434        }
58435      }
58436      return index;
58437    };
58438
58439    Line.prototype.onGridClick = function(x, y) {
58440      var index;
58441      index = this.hitTest(x);
58442      return this.fire('click', index, this.data[index].src, x, y);
58443    };
58444
58445    Line.prototype.onHoverMove = function(x, y) {
58446      var index;
58447      index = this.hitTest(x);
58448      return this.displayHoverForRow(index);
58449    };
58450
58451    Line.prototype.onHoverOut = function() {
58452      if (this.options.hideHover !== false) {
58453        return this.displayHoverForRow(null);
58454      }
58455    };
58456
58457    Line.prototype.displayHoverForRow = function(index) {
58458      var _ref;
58459      if (index != null) {
58460        (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
58461        return this.hilight(index);
58462      } else {
58463        this.hover.hide();
58464        return this.hilight();
58465      }
58466    };
58467
58468    Line.prototype.hoverContentForRow = function(index) {
58469      var content, j, row, y, _i, _len, _ref;
58470      row = this.data[index];
58471      content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
58472      _ref = row.y;
58473      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
58474        y = _ref[j];
58475        content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n  " + this.options.labels[j] + ":\n  " + (this.yLabelFormat(y)) + "\n</div>";
58476      }
58477      if (typeof this.options.hoverCallback === 'function') {
58478        content = this.options.hoverCallback(index, this.options, content, row.src
58478);
58479      }
58480      return [content, row._x, row._ymax];
58481    };
58482
58483    Line.prototype.generatePaths = function() {
58484      var coords, i, r, smooth;
58485      return this.paths = (function() {
58486        var _i, _ref, _ref1, _results;
58487        _results = [];
58488        for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
58489          smooth = typeof this.options.smooth === "boolean" ? this.options.smooth : (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0);
58490          coords = (function() {
58491            var _j, _len, _ref2, _results1;
58492            _ref2 = this.data;
58493            _results1 = [];
58494            for (_j = 0, _len = _ref2.length; _j < _len; _j++) {
58495              r = _ref2[_j];
58496              if (r._y[i] !== void 0) {
58497                _results1.push({
58498                  x: r._x,
58499                  y: r._y[i]
58500                });
58501              }
58502            }
58503            return _results1;
58504          }).call(this);
58505          if (coords.length > 1) {
58506            _results.push(Morris.Line.createPath(coords, smooth, this.bottom));
58507          } else {
58508            _results.push(null);
58509          }
58510        }
58511        return _results;
58512      }).call(this);
58513    };
58514
58515    Line.prototype.draw = function() {
58516      var _ref;
58517      if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') {
58518        this.drawXAxis();
58519      }
58520      this.drawSeries();
58521      if (this.options.hideHover === false) {
58522        return this.displayHoverForRow(this.data.length - 1);
58523      }
58524    };
58525
58526    Line.prototype.drawXAxis = function() {
58527      var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results,
58528        _this = this;
58529      ypos = this.bottom + this.options.padding / 2;
58530      prevLabelMargin = null;
58531      prevAngleMargin = null;
58532      drawLabel = function(labelText, xpos) {
58533        var label, labelBox, margin, offset, textBox;
58534        label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText);
58535        textBox = label.getBBox();
58536        label.transform("r" + (-_this.options.xLabelAngle));
58537        labelBox = label.getBBox();
58538        label.transform("t0," + (labelBox.height / 2) + "...");
58539        if (_this.options.xLabelAngle !== 0) {
58540          offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0);
58541          label.transform("t" + offset + ",0...");
58542        }
58543        labelBox = label.getBBox();
58544        if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) {
58545          if (_this.options.xLabelAngle !== 0) {
58546            margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0);
58547            prevAngleMargin = labelBox.x - margin;
58548          }
58549          return prevLabelMargin = labelBox.x - _this.options.xLabelMargin;
58550        } else {
58551          return label.remove();
58552        }
58553      };
58554      if (this.options.parseTime) {
58555        if (this.data.length === 1 && this.options.xLabels === 'auto') {
58556          labels = [[this.data[0].label, this.data[0].x]];
58557        } else {
58558          labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat);
58559        }
58560      } else {
58561        labels = (function() {
58562          var _i, _len, _ref, _results;
58563          _ref = this.data;
58564          _results = [];
58565          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
58566            row = _ref[_i];
58567            _results.push([row.label, row.x]);
58568          }
58569          return _results;
58570        }).call(this);
58571      }
58572      labels.reverse();
58573      _results = [];
58574      for (_i = 0, _len = labels.length; _i < _len; _i++) {
58575        l = labels[_i];
58576        _results.push(drawLabel(l[0], l[1]));
58577      }
58578      return _results;
58579    };
58580
58581    Line.prototype.drawSeries = function() {
58582      var i, _i, _j, _ref, _ref1, _results;
58583      this.seriesPoints = [];
58584      for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
58585        this._drawLineFor(i);
58586      }
58587      _results = [];
58588      for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {
58589        _results.push(this._drawPointFor(i));
58590      }
58591      return _results;
58592    };
58593
58594    Line.prototype._drawPointFor = function(index) {
58595      var circle, row, _i, _len, _ref, _results;
58596      this.seriesPoints[index] = [];
58597      _ref = this.data;
58598      _results = [];
58599      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
58600        row = _ref[_i];
58601        circle = null;
58602        if (row._y[index] != null) {
58603          circle = this.drawLinePoint(row._x, row._y[index], this.colorFor(row, index, 'point'), index);
58604        }
58605        _results.push(this.seriesPoints[index].push(circle));
58606      }
58607      return _results;
58608    };
58609
58610    Line.prototype._drawLineFor = function(index) {
58611      var path;
58612      path = this.paths[index];
58613      if (path !== null) {
58614        return this.drawLinePath(path, this.colorFor(null, index, 'line'), index);
58615      }
58616    };
58617
58618    Line.createPath = function(coords, smooth, bottom) {
58619      var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len;
58620      path = "";
58621      if (smooth) {
58622        grads = Morris.Line.gradients(coords);
58623      }
58624      prevCoord = {
58625        y: null
58626      };
58627      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
58628        coord = coords[i];
58629        if (coord.y != null) {
58630          if (prevCoord.y != null) {
58631            if (smooth) {
58632              g = grads[i];
58633              lg = grads[i - 1];
58634              ix = (coord.x - prevCoord.x) / 4;
58635              x1 = prevCoord.x + ix;
58636              y1 = Math.min(bottom, prevCoord.y + ix * lg);
58637              x2 = coord.x - ix;
58638              y2 = Math.min(bottom, coord.y - ix * g);
58639              path += "C" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + coord.x + "," + coord.y;
58640            } else {
58641              path += "L" + coord.x + "," + coord.y;
58642            }
58643          } else {
58644            if (!smooth || (grads[i] != null)) {
58645              path += "M" + coord.x + "," + coord.y;
58646            }
58647          }
58648        }
58649        prevCoord = coord;
58650      }
58651      return path;
58652    };
58653
58654    Line.gradients = function(coords) {
58655      var coord, grad, i, nextCoord, prevCoord, _i, _len, _results;
58656      grad = function(a, b) {
58657        return (a.y - b.y) / (a.x - b.x);
58658      };
58659      _results = [];
58660      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
58661        coord = coords[i];
58662        if (coord.y != null) {
58663          nextCoord = coords[i + 1] || {
58664            y: null
58665          };
58666          prevCoord = coords[i - 1] || {
58667            y: null
58668          };
58669          if ((prevCoord.y != null) && (nextCoord.y != null)) {
58670            _results.push(grad(prevCoord, nextCoord));
58671          } else if (prevCoord.y != null) {
58672            _results.push(grad(prevCoord, coord));
58673          } else if (nextCoord.y != null) {
58674            _results.push(grad(coord, nextCoord));
58675          } else {
58676            _results.push(null);
58677          }
58678        } else {
58679          _results.push(null);
58680        }
58681      }
58682      return _results;
58683    };
58684
58685    Line.prototype.hilight = function(index) {
58686      var i, _i, _j, _ref, _ref1;
58687      if (this.prevHilight !== null && this.prevHilight !== index) {
58688        for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
58689          if (this.seriesPoints[i][this.prevHilight]) {
58690            this.seriesPoints[i][this.prevHilight].animate(this.pointShrinkSeries(i));
58691          }
58692        }
58693      }
58694      if (index !== null && this.prevHilight !== index) {
58695        for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
58696          if (this.seriesPoints[i][index]) {
58697            this.seriesPoints[i][index].animate(this.pointGrowSeries(i));
58698          }
58699        }
58700      }
58701      return this.prevHilight = index;
58702    };
58703
58704    Line.prototype.colorFor = function(row, sidx, type) {
58705      if (typeof this.options.lineColors === 'function') {
58706        return this.options.lineColors.call(this, row, sidx, type);
58707      } else if (type === 'point') {
58708        return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length];
58709      } else {
58710        return this.options.lineColors[sidx % this.options.lineColors.length];
58711      }
58712    };
58713
58714    Line.prototype.drawXAxisLabel = function(xPos, yPos, text) {
58715      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
58716    };
58717
58718    Line.prototype.drawLinePath = function(path, lineColor, lineIndex) {
58719      return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.lineWidthForSeries(lineIndex));
58720    };
58721
58722    Line.prototype.drawLinePoint = function(xPos, yPos, pointColor, lineIndex) {
58723      return this.raphael.circle(xPos, yPos, this.pointSizeForSeries(lineIndex)).attr('fill', pointColor).attr('stroke-width', this.pointStrokeWidthForSeries(lineIndex)).attr('stroke', this.pointStrokeColorForSeries(lineIndex));
58724    };
58725
58726    Line.prototype.pointStrokeWidthForSeries = function(index) {
58727      return this.options.pointStrokeWidths[index % this.options.pointStrokeWidths.length];
58728    };
58729
58730    Line.prototype.pointStrokeColorForSeries = function(index) {
58731      return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length];
58732    };
58733
58734    Line.prototype.lineWidthForSeries = function(index) {
58735      if (this.options.lineWidth instanceof Array) {
58736        return this.options.lineWidth[index % this.options.lineWidth.length];
58737      } else {
58738        return this.options.lineWidth;
58739      }
58740    };
58741
58742    Line.prototype.pointSizeForSeries = function(index) {
58743      if (this.options.pointSize instanceof Array) {
58744        return this.options.pointSize[index % this.options.pointSize.length];
58745      } else {
58746        return this.options.pointSize;
58747      }
58748    };
58749
58750    Line.prototype.pointGrowSeries = function(index) {
58751      return Raphael.animation({
58752        r: this.pointSizeForSeries(index) + 3
58753      }, 25, 'linear');
58754    };
58755
58756    Line.prototype.pointShrinkSeries = function(index) {
58757      return Raphael.animation({
58758        r: this.pointSizeForSeries(index)
58759      }, 25, 'linear');
58760    };
58761
58762    return Line;
58763
58764  })(Morris.Grid);
58765
58766  Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) {
58767    var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref;
58768    ddensity = 200 * (dmax - dmin) / pxwidth;
58769    d0 = new Date(dmin);
58770    spec = Morris.LABEL_SPECS[specName];
58771    if (spec === void 0) {
58772      _ref = Morris.AUTO_LABEL_ORDER;
58773      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
58774        name = _ref[_i];
58775        s = Morris.LABEL_SPECS[name];
58776        if (ddensity >= s.span) {
58777          spec = s;
58778          break;
58779        }
58780      }
58781    }
58782    if (spec === void 0) {
58783      spec = Morris.LABEL_SPECS["second"];
58784    }
58785    if (xLabelFormat) {
58786      spec = $.extend({}, spec, {
58787        fmt: xLabelFormat
58788      });
58789    }
58790    d = spec.start(d0);
58791    ret = [];
58792    while ((t = d.getTime()) <= dmax) {
58793      if (t >= dmin) {
58794        ret.push([spec.fmt(d), t]);
58795      }
58796      spec.incr(d);
58797    }
58798    return ret;
58799  };
58800
58801  minutesSpecHelper = function(interval) {
58802    return {
58803      span: interval * 60 * 1000,
58804      start: function(d) {
58805        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours());
58806      },
58807      fmt: function(d) {
58808        return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes()));
58809      },
58810      incr: function(d) {
58811        return d.setUTCMinutes(d.getUTCMinutes() + interval);
58812      }
58813    };
58814  };
58815
58816  secondsSpecHelper = function(interval) {
58817    return {
58818      span: interval * 1000,
58819      start: function(d) {
58820        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());
58821      },
58822      fmt: function(d) {
58823        return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds()));
58824      },
58825      incr: function(d) {
58826        return d.setUTCSeconds(d.getUTCSeconds() + interval);
58827      }
58828    };
58829  };
58830
58831  Morris.LABEL_SPECS = {
58832    "decade": {
58833      span: 172800000000,
58834      start: function(d) {
58835        return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1);
58836      },
58837      fmt: function(d) {
58838        return "" + (d.getFullYear());
58839      },
58840      incr: function(d) {
58841        return d.setFullYear(d.getFullYear() + 10);
58842      }
58843    },
58844    "year": {
58845      span: 17280000000,
58846      start: function(d) {
58847        return new Date(d.getFullYear(), 0, 1);
58848      },
58849      fmt: function(d) {
58850        return "" + (d.getFullYear());
58851      },
58852      incr: function(d) {
58853        return d.setFullYear(d.getFullYear() + 1);
58854      }
58855    },
58856    "month": {
58857      span: 2419200000,
58858      start: function(d) {
58859        return new Date(d.getFullYear(), d.getMonth(), 1);
58860      },
58861      fmt: function(d) {
58862        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1));
58863      },
58864      incr: function(d) {
58865        return d.setMonth(d.getMonth() + 1);
58866      }
58867    },
58868    "week": {
58869      span: 604800000,
58870      start: function(d) {
58871        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
58872      },
58873      fmt: function(d) {
58874        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate()));
58875      },
58876      incr: function(d) {
58877        return d.setDate(d.getDate() + 7);
58878      }
58879    },
58880    "day": {
58881      span: 86400000,
58882      start: function(d) {
58883        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
58884      },
58885      fmt: function(d) {
58886        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate()));
58887      },
58888      incr: function(d) {
58889        return d.setDate(d.getDate() + 1);
58890      }
58891    },
58892    "hour": minutesSpecHelper(60),
58893    "30min": minutesSpecHelper(30),
58894    "15min": minutesSpecHelper(15),
58895    "10min": minutesSpecHelper(10),
58896    "5min": minutesSpecHelper(5),
58897    "minute": minutesSpecHelper(1),
58898    "30sec": secondsSpecHelper(30),
58899    "15sec": secondsSpecHelper(15),
58900    "10sec": secondsSpecHelper(10),
58901    "5sec": secondsSpecHelper(5),
58902    "second": secondsSpecHelper(1)
58903  };
58904
58905  Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "week", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
58906
58907  Morris.Area = (function(_super) {
58908    var areaDefaults;
58909
58910    __extends(Area, _super);
58911
58912    areaDefaults = {
58913      fillOpacity: 'auto',
58914      behaveLikeLine: false
58915    };
58916
58917    function Area(options) {
58918      var areaOptions;
58919      if (!(this instanceof Morris.Area)) {
58920        return new Morris.Area(options);
58921      }
58922      areaOptions = $.extend({}, areaDefaults, options);
58923      this.cumulative = !areaOptions.behaveLikeLine;
58924      if (areaOptions.fillOpacity === 'auto') {
58925        areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1;
58926      }
58927      Area.__super__.constructor.call(this, areaOptions);
58928    }
58929
58930    Area.prototype.calcPoints = function() {
58931      var row, total, y, _i, _len, _ref, _results;
58932      _ref = this.data;
58933      _results = [];
58934      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
58935        row = _ref[_i];
58936        row._x = this.transX(row.x);
58937        total = 0;
58938        row._y = (function() {
58939          var _j, _len1, _ref1, _results1;
58940          _ref1 = row.y;
58941          _results1 = [];
58942          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
58943            y = _ref1[_j];
58944            if (this.options.behaveLikeLine) {
58945              _results1.push(this.transY(y));
58946            } else {
58947              total += y || 0;
58948              _results1.push(this.transY(total));
58949            }
58950          }
58951          return _results1;
58952        }).call(this);
58953        _results.push(row._ymax = Math.max.apply(Math, row._y));
58954      }
58955      return _results;
58956    };
58957
58958    Area.prototype.drawSeries = function() {
58959      var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2;
58960      this.seriesPoints = [];
58961      if (this.options.behaveLikeLine) {
58962        range = (function() {
58963          _results = [];
58964          for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
58965          return _results;
58966        }).apply(this);
58967      } else {
58968        range = (function() {
58969          _results1 = [];
58970          for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); }
58971          return _results1;
58972        }).apply(this);
58973      }
58974      _results2 = [];
58975      for (_k = 0, _len = range.length; _k < _len; _k++) {
58976        i = range[_k];
58977        this._drawFillFor(i);
58978        this._drawLineFor(i);
58979        _results2.push(this._drawPointFor(i));
58980      }
58981      return _results2;
58982    };
58983
58984    Area.prototype._drawFillFor = function(index) {
58985      var path;
58986      path = this.paths[index];
58987      if (path !== null) {
58988        path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z");
58989        return this.drawFilledPath(path, this.fillForSeries(index));
58990      }
58991    };
58992
58993    Area.prototype.fillForSeries = function(i) {
58994      var color;
58995      color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line'));
58996      return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25));
58997    };
58998
58999    Area.prototype.drawFilledPath = function(path, fill) {
59000      return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke', 'none');
59001    };
59002
59003    return Area;
59004
59005  })(Morris.Line);
59006
59007  Morris.Bar = (function(_super) {
59008    __extends(Bar, _super);
59009
59010    function Bar(options) {
59011      this.onHoverOut = __bind(this.onHoverOut, this);
59012      this.onHoverMove = __bind(this.onHoverMove, this);
59013      this.onGridClick = __bind(this.onGridClick, this);
59014      if (!(this instanceof Morris.Bar)) {
59015        return new Morris.Bar(options);
59016      }
59017      Bar.__super__.constructor.call(this, $.extend({}, options, {
59018        parseTime: false
59019      }));
59020    }
59021
59022    Bar.prototype.init = function() {
59023      this.cumulative = this.options.stacked;
59024      if (this.options.hideHover !== 'always') {
59025        this.hover = new Morris.Hover({
59026          parent: this.el
59027        });
59028        this.on('hovermove', this.onHoverMove);
59029        this.on('hoverout', this.onHoverOut);
59030        return this.on('gridclick', this.onGridClick);
59031      }
59032    };
59033
59034    Bar.prototype.defaults = {
59035      barSizeRatio: 0.75,
59036      barGap: 3,
59037      barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
59038      barOpacity: 1.0,
59039      barRadius: [0, 0, 0, 0],
59040      xLabelMargin: 50
59041    };
59042
59043    Bar.prototype.calc = function() {
59044      var _ref;
59045      this.calcBars();
59046      if (this.options.hideHover === false) {
59047        return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1));
59048      }
59049    };
59050
59051    Bar.prototype.calcBars = function() {
59052      var idx, row, y, _i, _len, _ref, _results;
59053      _ref = this.data;
59054      _results = [];
59055      for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
59056        row = _ref[idx];
59057        row._x = this.left + this.width * (idx + 0.5) / this.data.length;
59058        _results.push(row._y = (function() {
59059          var _j, _len1, _ref1, _results1;
59060          _ref1 = row.y;
59061          _results1 = [];
59062          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
59063            y = _ref1[_j];
59064            if (y != null) {
59065              _results1.push(this.transY(y));
59066            } else {
59067              _results1.push(null);
59068            }
59069          }
59070          return _results1;
59071        }).call(this));
59072      }
59073      return _results;
59074    };
59075
59076    Bar.prototype.draw = function() {
59077      var _ref;
59078      if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') {
59079        this.drawXAxis();
59080      }
59081      return this.drawSeries();
59082    };
59083
59084    Bar.prototype.drawXAxis = function() {
59085      var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results;
59086      ypos = this.bottom + (this.options.xAxisLabelTopPadding || this.options.padding / 2);
59087      prevLabelMargin = null;
59088      prevAngleMargin = null;
59089      _results = [];
59090      for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
59091        row = this.data[this.data.length - 1 - i];
59092        label = this.drawXAxisLabel(row._x, ypos, row.label);
59093        textBox = label.getBBox();
59094        label.transform("r" + (-this.options.xLabelAngle));
59095        labelBox = label.getBBox();
59096        label.transform("t0," + (labelBox.height / 2) + "...");
59097        if (this.options.xLabelAngle !== 0) {
59098          offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0);
59099          label.transform("t" + offset + ",0...");
59100        }
59101        if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) {
59102          if (this.options.xLabelAngle !== 0) {
59103            margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0);
59104            prevAngleMargin = labelBox.x - margin;
59105          }
59106          _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin);
59107        } else {
59108          _results.push(label.remove());
59109        }
59110      }
59111      return _results;
59112    };
59113
59114    Bar.prototype.drawSeries = function() {
59115      var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, space
59115Left, top, ypos, zeroPos;
59116      groupWidth = this.width / this.options.data.length;
59117      numBars = this.options.stacked ? 1 : this.options.ykeys.length;
59118      barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars;
59119      if (this.options.barSize) {
59120        barWidth = Math.min(barWidth, this.options.barSize);
59121      }
59122      spaceLeft = groupWidth - barWidth * numBars - this.options.barGap * (numBars - 1);
59123      leftPadding = spaceLeft / 2;
59124      zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null;
59125      return this.bars = (function() {
59126        var _i, _len, _ref, _results;
59127        _ref = this.data;
59128        _results = [];
59129        for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
59130          row = _ref[idx];
59131          lastTop = 0;
59132          _results.push((function() {
59133            var _j, _len1, _ref1, _results1;
59134            _ref1 = row._y;
59135            _results1 = [];
59136            for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) {
59137              ypos = _ref1[sidx];
59138              if (ypos !== null) {
59139                if (zeroPos) {
59140                  top = Math.min(ypos, zeroPos);
59141                  bottom = Math.max(ypos, zeroPos);
59142                } else {
59143                  top = ypos;
59144                  bottom = this.bottom;
59145                }
59146                left = this.left + idx * groupWidth + leftPadding;
59147                if (!this.options.stacked) {
59148                  left += sidx * (barWidth + this.options.barGap);
59149                }
59150                size = bottom - top;
59151                if (this.options.verticalGridCondition && this.options.verticalGridCondition(row.x)) {
59152                  this.drawBar(this.left + idx * groupWidth, this.top, groupWidth, Math.abs(this.top - this.bottom), this.options.verticalGridColor, this.options.verticalGridOpacity, this.options.barRadius);
59153                }
59154                if (this.options.stacked) {
59155                  top -= lastTop;
59156                }
59157                this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'), this.options.barOpacity, this.options.barRadius);
59158                _results1.push(lastTop += size);
59159              } else {
59160                _results1.push(null);
59161              }
59162            }
59163            return _results1;
59164          }).call(this));
59165        }
59166        return _results;
59167      }).call(this);
59168    };
59169
59170    Bar.prototype.colorFor = function(row, sidx, type) {
59171      var r, s;
59172      if (typeof this.options.barColors === 'function') {
59173        r = {
59174          x: row.x,
59175          y: row.y[sidx],
59176          label: row.label
59177        };
59178        s = {
59179          index: sidx,
59180          key: this.options.ykeys[sidx],
59181          label: this.options.labels[sidx]
59182        };
59183        return this.options.barColors.call(this, r, s, type);
59184      } else {
59185        return this.options.barColors[sidx % this.options.barColors.length];
59186      }
59187    };
59188
59189    Bar.prototype.hitTest = function(x) {
59190      if (this.data.length === 0) {
59191        return null;
59192      }
59193      x = Math.max(Math.min(x, this.right), this.left);
59194      return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length)));
59195    };
59196
59197    Bar.prototype.onGridClick = function(x, y) {
59198      var index;
59199      index = this.hitTest(x);
59200      return this.fire('click', index, this.data[index].src, x, y);
59201    };
59202
59203    Bar.prototype.onHoverMove = function(x, y) {
59204      var index, _ref;
59205      index = this.hitTest(x);
59206      return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
59207    };
59208
59209    Bar.prototype.onHoverOut = function() {
59210      if (this.options.hideHover !== false) {
59211        return this.hover.hide();
59212      }
59213    };
59214
59215    Bar.prototype.hoverContentForRow = function(index) {
59216      var content, j, row, x, y, _i, _len, _ref;
59217      row = this.data[index];
59218      content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
59219      _ref = row.y;
59220      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
59221        y = _ref[j];
59222        content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n  " + this.options.labels[j] + ":\n  " + (this.yLabelFormat(y)) + "\n</div>";
59223      }
59224      if (typeof this.options.hoverCallback === 'function') {
59225        content = this.options.hoverCallback(index, this.options, content, row.src
59225);
59226      }
59227      x = this.left + (index + 0.5) * this.width / this.data.length;
59228      return [content, x];
59229    };
59230
59231    Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) {
59232      var label;
59233      return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
59234    };
59235
59236    Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor, opacity, radiusArray) {
59237      var maxRadius, path;
59238      maxRadius = Math.max.apply(Math, radiusArray);
59239      if (maxRadius === 0 || maxRadius > height) {
59240        path = this.raphael.rect(xPos, yPos, width, height);
59241      } else {
59242        path = this.raphael.path(this.roundedRect(xPos, yPos, width, height, radiusArray));
59243      }
59244      return path.attr('fill', barColor).attr('fill-opacity', opacity).attr('stroke', 'none');
59245    };
59246
59247    Bar.prototype.roundedRect = function(x, y, w, h, r) {
59248      if (r == null) {
59249        r = [0, 0, 0, 0];
59250      }
59251      return ["M", x, r[0] + y, "Q", x, y, x + r[0], y, "L", x + w - r[1], y, "Q", x + w, y, x + w, y + r[1], "L", x + w, y + h - r[2], "Q", x + w, y + h, x + w - r[2], y + h, "L", x + r[3], y + h, "Q", x, y + h, x, y + h - r[3], "Z"];
59252    };
59253
59254    return Bar;
59255
59256  })(Morris.Grid);
59257
59258  Morris.Donut = (function(_super) {
59259    __extends(Donut, _super);
59260
59261    Donut.prototype.defaults = {
59262      colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],
59263      backgroundColor: '#FFFFFF',
59264      labelColor: '#000000',
59265      formatter: Morris.commas,
59266      resize: false
59267    };
59268
59269    function Donut(options) {
59270      this.resizeHandler = __bind(this.resizeHandler, this);
59271      this.select = __bind(this.select, this);
59272      this.click = __bind(this.click, this);
59273      var _this = this;
59274      if (!(this instanceof Morris.Donut)) {
59275        return new Morris.Donut(options);
59276      }
59277      this.options = $.extend({}, this.defaults, options);
59278      if (typeof options.element === 'string') {
59279        this.el = $(document.getElementById(options.element));
59280      } else {
59281        this.el = $(options.element);
59282      }
59283      if (this.el === null || this.el.length === 0) {
59284        throw new Error("Graph placeholder not found.");
59285      }
59286      if (options.data === void 0 || options.data.length === 0) {
59287        return;
59288      }
59289      this.raphael = new Raphael(this.el[0]);
59290      if (this.options.resize) {
59291        $(window).bind('resize', function(evt) {
59292          if (_this.timeoutId != null) {
59293            window.clearTimeout(_this.timeoutId);
59294          }
59295          return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);
59296        });
59297      }
59298      this.setData(options.data);
59299    }
59300
59301    Donut.prototype.redraw = function() {
59302      var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
59303      this.raphael.clear();
59304      cx = this.el.width() / 2;
59305      cy = this.el.height() / 2;
59306      w = (Math.min(cx, cy) - 10) / 3;
59307      total = 0;
59308      _ref = this.values;
59309      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
59310        value = _ref[_i];
59311        total += value;
59312      }
59313      min = 5 / (2 * w);
59314      C = 1.9999 * Math.PI - min * this.data.length;
59315      last = 0;
59316      idx = 0;
59317      this.segments = [];
59318      _ref1 = this.values;
59319      for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
59320        value = _ref1[i];
59321        next = last + min + C * (value / total);
59322        seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.data[i].color || this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);
59323        seg.render();
59324        this.segments.push(seg);
59325        seg.on('hover', this.select);
59326        seg.on('click', this.click);
59327        last = next;
59328        idx += 1;
59329      }
59330      this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
59331      this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
59332      max_value = Math.max.apply(Math, this.values);
59333      idx = 0;
59334      _ref2 = this.values;
59335      _results = [];
59336      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
59337        value = _ref2[_k];
59338        if (value === max_value) {
59339          this.select(idx);
59340          break;
59341        }
59342        _results.push(idx += 1);
59343      }
59344      return _results;
59345    };
59346
59347    Donut.prototype.setData = function(data) {
59348      var row;
59349      this.data = data;
59350      this.values = (function() {
59351        var _i, _len, _ref, _results;
59352        _ref = this.data;
59353        _results = [];
59354        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
59355          row = _ref[_i];
59356          _results.push(parseFloat(row.value));
59357        }
59358        return _results;
59359      }).call(this);
59360      return this.redraw();
59361    };
59362
59363    Donut.prototype.click = function(idx) {
59364      return this.fire('click', idx, this.data[idx]);
59365    };
59366
59367    Donut.prototype.select = function(idx) {
59368      var row, s, segment, _i, _len, _ref;
59369      _ref = this.segments;
59370      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
59371        s = _ref[_i];
59372        s.deselect();
59373      }
59374      segment = this.segments[idx];
59375      segment.select();
59376      row = this.data[idx];
59377      return this.setLabels(row.label, this.options.formatter(row.value, row));
59378    };
59379
59380    Donut.prototype.setLabels = function(label1, label2) {
59381      var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale;
59382      inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3;
59383      maxWidth = 1.8 * inner;
59384      maxHeightTop = inner / 2;
59385      maxHeightBottom = inner / 3;
59386      this.text1.attr({
59387        text: label1,
59388        transform: ''
59389      });
59390      text1bbox = this.text1.getBBox();
59391      text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height);
59392      this.text1.attr({
59393        transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height)
59394      });
59395      this.text2.attr({
59396        text: label2,
59397        transform: ''
59398      });
59399      text2bbox = this.text2.getBBox();
59400      text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height);
59401      return this.text2.attr({
59402        transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y
59403      });
59404    };
59405
59406    Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) {
59407      var text;
59408      text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color);
59409      if (fontWeight != null) {
59410        text.attr('font-weight', fontWeight);
59411      }
59412      return text;
59413    };
59414
59415    Donut.prototype.resizeHandler = function() {
59416      this.timeoutId = null;
59417      this.raphael.setSize(this.el.width(), this.el.height());
59418      return this.redraw();
59419    };
59420
59421    return Donut;
59422
59423  })(Morris.EventEmitter);
59424
59425  Morris.DonutSegment = (function(_super) {
59426    __extends(DonutSegment, _super);
59427
59428    function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) {
59429      this.cx = cx;
59430      this.cy = cy;
59431      this.inner = inner;
59432      this.outer = outer;
59433      this.color = color;
59434      this.backgroundColor = backgroundColor;
59435      this.index = index;
59436      this.raphael = raphael;
59437      this.deselect = __bind(this.deselect, this);
59438      this.select = __bind(this.select, this);
59439      this.sin_p0 = Math.sin(p0);
59440      this.cos_p0 = Math.cos(p0);
59441      this.sin_p1 = Math.sin(p1);
59442      this.cos_p1 = Math.cos(p1);
59443      this.is_long = (p1 - p0) > Math.PI ? 1 : 0;
59444      this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5);
59445      this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer);
59446      this.hilight = this.calcArc(this.inner);
59447    }
59448
59449    DonutSegment.prototype.calcArcPoints = function(r) {
59450      return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1];
59451    };
59452
59453    DonutSegment.prototype.calcSegment = function(r1, r2) {
59454      var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1;
59455      _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 
59455= _ref[2], iy1 = _ref[3];
59456      _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3];
59457      return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.is_long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.is_long + ",1," + ox0 + "," + oy0) + "Z";
59458    };
59459
59460    DonutSegment.prototype.calcArc = function(r) {
59461      var ix0, ix1, iy0, iy1, _ref;
59462      _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];
59463      return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.is_long + ",0," + ix1 + "," + iy1);
59464    };
59465
59466    DonutSegment.prototype.render = function() {
59467      var _this = this;
59468      this.arc = this.drawDonutArc(this.hilight, this.color);
59469      return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() {
59470        return _this.fire('hover', _this.index);
59471      }, function() {
59472        return _this.fire('click', _this.index);
59473      });
59474    };
59475
59476    DonutSegment.prototype.drawDonutArc = function(path, color) {
59477      return this.raphael.path(path).attr({
59478        stroke: color,
59479        'stroke-width': 2,
59480        opacity: 0
59481      });
59482    };
59483
59484    DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) {
59485      return this.raphael.path(path).attr({
59486        fill: fillColor,
59487        stroke: strokeColor,
59488        'stroke-width': 3
59489      }).hover(hoverFunction).click(clickFunction);
59490    };
59491
59492    DonutSegment.prototype.select = function() {
59493      if (!this.selected) {
59494        this.seg.animate({
59495          path: this.selectedPath
59496        }, 150, '<>');
59497        this.arc.animate({
59498          opacity: 1
59499        }, 150, '<>');
59500        return this.selected = true;
59501      }
59502    };
59503
59504    DonutSegment.prototype.deselect = function() {
59505      if (this.selected) {
59506        this.seg.animate({
59507          path: this.path
59508        }, 150, '<>');
59509        this.arc.animate({
59510          opacity: 0
59511        }, 150, '<>');
59512        return this.selected = false;
59513      }
59514    };
59515
59516    return DonutSegment;
59517
59518  })(Morris.EventEmitter);
59519
59520}).call(this);
59521
59522/*!
59523 * Chart.js v2.8.0
59524 * https://www.chartjs.org
59525 * (c) 2019 Chart.js Contributors
59526 * Released under the MIT License
59527 */
59528(function (global, factory) {
59529typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
59530typeof define === 'function' && define.amd ? define(factory) :
59531(global.Chart = factory());
59532}(this, (function () { 'use strict';
59533
59534/* MIT license */
59535
59536var conversions = {
59537  rgb2hsl: rgb2hsl,
59538  rgb2hsv: rgb2hsv,
59539  rgb2hwb: rgb2hwb,
59540  rgb2cmyk: rgb2cmyk,
59541  rgb2keyword: rgb2keyword,
59542  rgb2xyz: rgb2xyz,
59543  rgb2lab: rgb2lab,
59544  rgb2lch: rgb2lch,
59545
59546  hsl2rgb: hsl2rgb,
59547  hsl2hsv: hsl2hsv,
59548  hsl2hwb: hsl2hwb,
59549  hsl2cmyk: hsl2cmyk,
59550  hsl2keyword: hsl2keyword,
59551
59552  hsv2rgb: hsv2rgb,
59553  hsv2hsl: hsv2hsl,
59554  hsv2hwb: hsv2hwb,
59555  hsv2cmyk: hsv2cmyk,
59556  hsv2keyword: hsv2keyword,
59557
59558  hwb2rgb: hwb2rgb,
59559  hwb2hsl: hwb2hsl,
59560  hwb2hsv: hwb2hsv,
59561  hwb2cmyk: hwb2cmyk,
59562  hwb2keyword: hwb2keyword,
59563
59564  cmyk2rgb: cmyk2rgb,
59565  cmyk2hsl: cmyk2hsl,
59566  cmyk2hsv: cmyk2hsv,
59567  cmyk2hwb: cmyk2hwb,
59568  cmyk2keyword: cmyk2keyword,
59569
59570  keyword2rgb: keyword2rgb,
59571  keyword2hsl: keyword2hsl,
59572  keyword2hsv: keyword2hsv,
59573  keyword2hwb: keyword2hwb,
59574  keyword2cmyk: keyword2cmyk,
59575  keyword2lab: keyword2lab,
59576  keyword2xyz: keyword2xyz,
59577
59578  xyz2rgb: xyz2rgb,
59579  xyz2lab: xyz2lab,
59580  xyz2lch: xyz2lch,
59581
59582  lab2xyz: lab2xyz,
59583  lab2rgb: lab2rgb,
59584  lab2lch: lab2lch,
59585
59586  lch2lab: lch2lab,
59587  lch2xyz: lch2xyz,
59588  lch2rgb: lch2rgb
59589};
59590
59591
59592function rgb2hsl(rgb) {
59593  var r = rgb[0]/255,
59594      g = rgb[1]/255,
59595      b = rgb[2]/255,
59596      min = Math.min(r, g, b),
59597      max = Math.max(r, g, b),
59598      delta = max - min,
59599      h, s, l;
59600
59601  if (max == min)
59602    h = 0;
59603  else if (r == max)
59604    h = (g - b) / delta;
59605  else if (g == max)
59606    h = 2 + (b - r) / delta;
59607  else if (b == max)
59608    h = 4 + (r - g)/ delta;
59609
59610  h = Math.min(h * 60, 360);
59611
59612  if (h < 0)
59613    h += 360;
59614
59615  l = (min + max) / 2;
59616
59617  if (max == min)
59618    s = 0;
59619  else if (l <= 0.5)
59620    s = delta / (max + min);
59621  else
59622    s = delta / (2 - max - min);
59623
59624  return [h, s * 100, l * 100];
59625}
59626
59627function rgb2hsv(rgb) {
59628  var r = rgb[0],
59629      g = rgb[1],
59630      b = rgb[2],
59631      min = Math.min(r, g, b),
59632      max = Math.max(r, g, b),
59633      delta = max - min,
59634      h, s, v;
59635
59636  if (max == 0)
59637    s = 0;
59638  else
59639    s = (delta/max * 1000)/10;
59640
59641  if (max == min)
59642    h = 0;
59643  else if (r == max)
59644    h = (g - b) / delta;
59645  else if (g == max)
59646    h = 2 + (b - r) / delta;
59647  else if (b == max)
59648    h = 4 + (r - g) / delta;
59649
59650  h = Math.min(h * 60, 360);
59651
59652  if (h < 0)
59653    h += 360;
59654
59655  v = ((max / 255) * 1000) / 10;
59656
59657  return [h, s, v];
59658}
59659
59660function rgb2hwb(rgb) {
59661  var r = rgb[0],
59662      g = rgb[1],
59663      b = rgb[2],
59664      h = rgb2hsl(rgb)[0],
59665      w = 1/255 * Math.min(r, Math.min(g, b)),
59666      b = 1 - 1/255 * Math.max(r, Math.max(g, b));
59667
59668  return [h, w * 100, b * 100];
59669}
59670
59671function rgb2cmyk(rgb) {
59672  var r = rgb[0] / 255,
59673      g = rgb[1] / 255,
59674      b = rgb[2] / 255,
59675      c, m, y, k;
59676
59677  k = Math.min(1 - r, 1 - g, 1 - b);
59678  c = (1 - r - k) / (1 - k) || 0;
59679  m = (1 - g - k) / (1 - k) || 0;
59680  y = (1 - b - k) / (1 - k) || 0;
59681  return [c * 100, m * 100, y * 100, k * 100];
59682}
59683
59684function rgb2keyword(rgb) {
59685  return reverseKeywords[JSON.stringify(rgb)];
59686}
59687
59688function rgb2xyz(rgb) {
59689  var r = rgb[0] / 255,
59690      g = rgb[1] / 255,
59691      b = rgb[2] / 255;
59692
59693  // assume sRGB
59694  r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
59695  g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
59696  b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
59697
59698  var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
59699  var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
59700  var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
59701
59702  return [x * 100, y *100, z * 100];
59703}
59704
59705function rgb2lab(rgb) {
59706  var xyz = rgb2xyz(rgb),
59707        x = xyz[0],
59708        y = xyz[1],
59709        z = xyz[2],
59710        l, a, b;
59711
59712  x /= 95.047;
59713  y /= 100;
59714  z /= 108.883;
59715
59716  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
59717  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
59718  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
59719
59720  l = (116 * y) - 16;
59721  a = 500 * (x - y);
59722  b = 200 * (y - z);
59723
59724  return [l, a, b];
59725}
59726
59727function rgb2lch(args) {
59728  return lab2lch(rgb2lab(args));
59729}
59730
59731function hsl2rgb(hsl) {
59732  var h = hsl[0] / 360,
59733      s = hsl[1] / 100,
59734      l = hsl[2] / 100,
59735      t1, t2, t3, rgb, val;
59736
59737  if (s == 0) {
59738    val = l * 255;
59739    return [val, val, val];
59740  }
59741
59742  if (l < 0.5)
59743    t2 = l * (1 + s);
59744  else
59745    t2 = l + s - l * s;
59746  t1 = 2 * l - t2;
59747
59748  rgb = [0, 0, 0];
59749  for (var i = 0; i < 3; i++) {
59750    t3 = h + 1 / 3 * - (i - 1);
59751    t3 < 0 && t3++;
59752    t3 > 1 && t3--;
59753
59754    if (6 * t3 < 1)
59755      val = t1 + (t2 - t1) * 6 * t3;
59756    else if (2 * t3 < 1)
59757      val = t2;
59758    else if (3 * t3 < 2)
59759      val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
59760    else
59761      val = t1;
59762
59763    rgb[i] = val * 255;
59764  }
59765
59766  return rgb;
59767}
59768
59769function hsl2hsv(hsl) {
59770  var h = hsl[0],
59771      s = hsl[1] / 100,
59772      l = hsl[2] / 100,
59773      sv, v;
59774
59775  if(l === 0) {
59776      // no need to do calc on black
59777      // also avoids divide by 0 error
59778      return [0, 0, 0];
59779  }
59780
59781  l *= 2;
59782  s *= (l <= 1) ? l : 2 - l;
59783  v = (l + s) / 2;
59784  sv = (2 * s) / (l + s);
59785  return [h, sv * 100, v * 100];
59786}
59787
59788function hsl2hwb(args) {
59789  return rgb2hwb(hsl2rgb(args));
59790}
59791
59792function hsl2cmyk(args) {
59793  return rgb2cmyk(hsl2rgb(args));
59794}
59795
59796function hsl2keyword(args) {
59797  return rgb2keyword(hsl2rgb(args));
59798}
59799
59800
59801function hsv2rgb(hsv) {
59802  var h = hsv[0] / 60,
59803      s = hsv[1] / 100,
59804      v = hsv[2] / 100,
59805      hi = Math.floor(h) % 6;
59806
59807  var f = h - Math.floor(h),
59808      p = 255 * v * (1 - s),
59809      q = 255 * v * (1 - (s * f)),
59810      t = 255 * v * (1 - (s * (1 - f))),
59811      v = 255 * v;
59812
59813  switch(hi) {
59814    case 0:
59815      return [v, t, p];
59816    case 1:
59817      return [q, v, p];
59818    case 2:
59819      return [p, v, t];
59820    case 3:
59821      return [p, q, v];
59822    case 4:
59823      return [t, p, v];
59824    case 5:
59825      return [v, p, q];
59826  }
59827}
59828
59829function hsv2hsl(hsv) {
59830  var h = hsv[0],
59831      s = hsv[1] / 100,
59832      v = hsv[2] / 100,
59833      sl, l;
59834
59835  l = (2 - s) * v;
59836  sl = s * v;
59837  sl /= (l <= 1) ? l : 2 - l;
59838  sl = sl || 0;
59839  l /= 2;
59840  return [h, sl * 100, l * 100];
59841}
59842
59843function hsv2hwb(args) {
59844  return rgb2hwb(hsv2rgb(args))
59845}
59846
59847function hsv2cmyk(args) {
59848  return rgb2cmyk(hsv2rgb(args));
59849}
59850
59851function hsv2keyword(args) {
59852  return rgb2keyword(hsv2rgb(args));
59853}
59854
59855// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
59856function hwb2rgb(hwb) {
59857  var h = hwb[0] / 360,
59858      wh = hwb[1] / 100,
59859      bl = hwb[2] / 100,
59860      ratio = wh + bl,
59861      i, v, f, n;
59862
59863  // wh + bl cant be > 1
59864  if (ratio > 1) {
59865    wh /= ratio;
59866    bl /= ratio;
59867  }
59868
59869  i = Math.floor(6 * h);
59870  v = 1 - bl;
59871  f = 6 * h - i;
59872  if ((i & 0x01) != 0) {
59873    f = 1 - f;
59874  }
59875  n = wh + f * (v - wh);  // linear interpolation
59876
59877  switch (i) {
59878    default:
59879    case 6:
59880    case 0: r = v; g = n; b = wh; break;
59881    case 1: r = n; g = v; b = wh; break;
59882    case 2: r = wh; g = v; b = n; break;
59883    case 3: r = wh; g = n; b = v; break;
59884    case 4: r = n; g = wh; b = v; break;
59885    case 5: r = v; g = wh; b = n; break;
59886  }
59887
59888  return [r * 255, g * 255, b * 255];
59889}
59890
59891function hwb2hsl(args) {
59892  return rgb2hsl(hwb2rgb(args));
59893}
59894
59895function hwb2hsv(args) {
59896  return rgb2hsv(hwb2rgb(args));
59897}
59898
59899function hwb2cmyk(args) {
59900  return rgb2cmyk(hwb2rgb(args));
59901}
59902
59903function hwb2keyword(args) {
59904  return rgb2keyword(hwb2rgb(args));
59905}
59906
59907function cmyk2rgb(cmyk) {
59908  var c = cmyk[0] / 100,
59909      m = cmyk[1] / 100,
59910      y = cmyk[2] / 100,
59911      k = cmyk[3] / 100,
59912      r, g, b;
59913
59914  r = 1 - Math.min(1, c * (1 - k) + k);
59915  g = 1 - Math.min(1, m * (1 - k) + k);
59916  b = 1 - Math.min(1, y * (1 - k) + k);
59917  return [r * 255, g * 255, b * 255];
59918}
59919
59920function cmyk2hsl(args) {
59921  return rgb2hsl(cmyk2rgb(args));
59922}
59923
59924function cmyk2hsv(args) {
59925  return rgb2hsv(cmyk2rgb(args));
59926}
59927
59928function cmyk2hwb(args) {
59929  return rgb2hwb(cmyk2rgb(args));
59930}
59931
59932function cmyk2keyword(args) {
59933  return rgb2keyword(cmyk2rgb(args));
59934}
59935
59936
59937function xyz2rgb(xyz) {
59938  var x = xyz[0] / 100,
59939      y = xyz[1] / 100,
59940      z = xyz[2] / 100,
59941      r, g, b;
59942
59943  r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
59944  g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
59945  b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
59946
59947  // assume sRGB
59948  r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
59949    : r = (r * 12.92);
59950
59951  g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
59952    : g = (g * 12.92);
59953
59954  b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
59955    : b = (b * 12.92);
59956
59957  r = Math.min(Math.max(0, r), 1);
59958  g = Math.min(Math.max(0, g), 1);
59959  b = Math.min(Math.max(0, b), 1);
59960
59961  return [r * 255, g * 255, b * 255];
59962}
59963
59964function xyz2lab(xyz) {
59965  var x = xyz[0],
59966      y = xyz[1],
59967      z = xyz[2],
59968      l, a, b;
59969
59970  x /= 95.047;
59971  y /= 100;
59972  z /= 108.883;
59973
59974  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
59975  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
59976  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
59977
59978  l = (116 * y) - 16;
59979  a = 500 * (x - y);
59980  b = 200 * (y - z);
59981
59982  return [l, a, b];
59983}
59984
59985function xyz2lch(args) {
59986  return lab2lch(xyz2lab(args));
59987}
59988
59989function lab2xyz(lab) {
59990  var l = lab[0],
59991      a = lab[1],
59992      b = lab[2],
59993      x, y, z, y2;
59994
59995  if (l <= 8) {
59996    y = (l * 100) / 903.3;
59997    y2 = (7.787 * (y / 100)) + (16 / 116);
59998  } else {
59999    y = 100 * Math.pow((l + 16) / 116, 3);
60000    y2 = Math.pow(y / 100, 1/3);
60001  }
60002
60003  x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3);
60004
60005  z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);
60006
60007  return [x, y, z];
60008}
60009
60010function lab2lch(lab) {
60011  var l = lab[0],
60012      a = lab[1],
60013      b = lab[2],
60014      hr, h, c;
60015
60016  hr = Math.atan2(b, a);
60017  h = hr * 360 / 2 / Math.PI;
60018  if (h < 0) {
60019    h += 360;
60020  }
60021  c = Math.sqrt(a * a + b * b);
60022  return [l, c, h];
60023}
60024
60025function lab2rgb(args) {
60026  return xyz2rgb(lab2xyz(args));
60027}
60028
60029function lch2lab(lch) {
60030  var l = lch[0],
60031      c = lch[1],
60032      h = lch[2],
60033      a, b, hr;
60034
60035  hr = h / 360 * 2 * Math.PI;
60036  a = c * Math.cos(hr);
60037  b = c * Math.sin(hr);
60038  return [l, a, b];
60039}
60040
60041function lch2xyz(args) {
60042  return lab2xyz(lch2lab(args));
60043}
60044
60045function lch2rgb(args) {
60046  return lab2rgb(lch2lab(args));
60047}
60048
60049function keyword2rgb(keyword) {
60050  return cssKeywords[keyword];
60051}
60052
60053function keyword2hsl(args) {
60054  return rgb2hsl(keyword2rgb(args));
60055}
60056
60057function keyword2hsv(args) {
60058  return rgb2hsv(keyword2rgb(args));
60059}
60060
60061function keyword2hwb(args) {
60062  return rgb2hwb(keyword2rgb(args));
60063}
60064
60065function keyword2cmyk(args) {
60066  return rgb2cmyk(keyword2rgb(args));
60067}
60068
60069function keyword2lab(args) {
60070  return rgb2lab(keyword2rgb(args));
60071}
60072
60073function keyword2xyz(args) {
60074  return rgb2xyz(keyword2rgb(args));
60075}
60076
60077var cssKeywords = {
60078  aliceblue:  [240,248,255],
60079  antiquewhite: [250,235,215],
60080  aqua: [0,255,255],
60081  aquamarine: [127,255,212],
60082  azure:  [240,255,255],
60083  beige:  [245,245,220],
60084  bisque: [255,228,196],
60085  black:  [0,0,0],
60086  blanchedalmond: [255,235,205],
60087  blue: [0,0,255],
60088  blueviolet: [138,43,226],
60089  brown:  [165,42,42],
60090  burlywood:  [222,184,135],
60091  cadetblue:  [95,158,160],
60092  chartreuse: [127,255,0],
60093  chocolate:  [210,105,30],
60094  coral:  [255,127,80],
60095  cornflowerblue: [100,149,237],
60096  cornsilk: [255,248,220],
60097  crimson:  [220,20,60],
60098  cyan: [0,255,255],
60099  darkblue: [0,0,139],
60100  darkcyan: [0,139,139],
60101  darkgoldenrod:  [184,134,11],
60102  darkgray: [169,169,169],
60103  darkgreen:  [0,100,0],
60104  darkgrey: [169,169,169],
60105  darkkhaki:  [189,183,107],
60106  darkmagenta:  [139,0,139],
60107  darkolivegreen: [85,107,47],
60108  darkorange: [255,140,0],
60109  darkorchid: [153,50,204],
60110  darkred:  [139,0,0],
60111  darksalmon: [233,150,122],
60112  darkseagreen: [143,188,143],
60113  darkslateblue:  [72,61,139],
60114  darkslategray:  [47,79,79],
60115  darkslategrey:  [47,79,79],
60116  darkturquoise:  [0,206,209],
60117  darkviolet: [148,0,211],
60118  deeppink: [255,20,147],
60119  deepskyblue:  [0,191,255],
60120  dimgray:  [105,105,105],
60121  dimgrey:  [105,105,105],
60122  dodgerblue: [30,144,255],
60123  firebrick:  [178,34,34],
60124  floralwhite:  [255,250,240],
60125  forestgreen:  [34,139,34],
60126  fuchsia:  [255,0,255],
60127  gainsboro:  [220,220,220],
60128  ghostwhite: [248,248,255],
60129  gold: [255,215,0],
60130  goldenrod:  [218,165,32],
60131  gray: [128,128,128],
60132  green:  [0,128,0],
60133  greenyellow:  [173,255,47],
60134  grey: [128,128,128],
60135  honeydew: [240,255,240],
60136  hotpink:  [255,105,180],
60137  indianred:  [205,92,92],
60138  indigo: [75,0,130],
60139  ivory:  [255,255,240],
60140  khaki:  [240,230,140],
60141  lavender: [230,230,250],
60142  lavenderblush:  [255,240,245],
60143  lawngreen:  [124,252,0],
60144  lemonchiffon: [255,250,205],
60145  lightblue:  [173,216,230],
60146  lightcoral: [240,128,128],
60147  lightcyan:  [224,255,255],
60148  lightgoldenrodyellow: [250,250,210],
60149  lightgray:  [211,211,211],
60150  lightgreen: [144,238,144],
60151  lightgrey:  [211,211,211],
60152  lightpink:  [255,182,193],
60153  lightsalmon:  [255,160,122],
60154  lightseagreen:  [32,178,170],
60155  lightskyblue: [135,206,250],
60156  lightslategray: [119,136,153],
60157  lightslategrey: [119,136,153],
60158  lightsteelblue: [176,196,222],
60159  lightyellow:  [255,255,224],
60160  lime: [0,255,0],
60161  limegreen:  [50,205,50],
60162  linen:  [250,240,230],
60163  magenta:  [255,0,255],
60164  maroon: [128,0,0],
60165  mediumaquamarine: [102,205,170],
60166  mediumblue: [0,0,205],
60167  mediumorchid: [186,85,211],
60168  mediumpurple: [147,112,219],
60169  mediumseagreen: [60,179,113],
60170  mediumslateblue:  [123,104,238],
60171  mediumspringgreen:  [0,250,154],
60172  mediumturquoise:  [72,209,204],
60173  mediumvioletred:  [199,21,133],
60174  midnightblue: [25,25,112],
60175  mintcream:  [245,255,250],
60176  mistyrose:  [255,228,225],
60177  moccasin: [255,228,181],
60178  navajowhite:  [255,222,173],
60179  navy: [0,0,128],
60180  oldlace:  [253,245,230],
60181  olive:  [128,128,0],
60182  olivedrab:  [107,142,35],
60183  orange: [255,165,0],
60184  orangered:  [255,69,0],
60185  orchid: [218,112,214],
60186  palegoldenrod:  [238,232,170],
60187  palegreen:  [152,251,152],
60188  paleturquoise:  [175,238,238],
60189  palevioletred:  [219,112,147],
60190  papayawhip: [255,239,213],
60191  peachpuff:  [255,218,185],
60192  peru: [205,133,63],
60193  pink: [255,192,203],
60194  plum: [221,160,221],
60195  powderblue: [176,224,230],
60196  purple: [128,0,128],
60197  rebeccapurple: [102, 51, 153],
60198  red:  [255,0,0],
60199  rosybrown:  [188,143,143],
60200  royalblue:  [65,105,225],
60201  saddlebrown:  [139,69,19],
60202  salmon: [250,128,114],
60203  sandybrown: [244,164,96],
60204  seagreen: [46,139,87],
60205  seashell: [255,245,238],
60206  sienna: [160,82,45],
60207  silver: [192,192,192],
60208  skyblue:  [135,206,235],
60209  slateblue:  [106,90,205],
60210  slategray:  [112,128,144],
60211  slategrey:  [112,128,144],
60212  snow: [255,250,250],
60213  springgreen:  [0,255,127],
60214  steelblue:  [70,130,180],
60215  tan:  [210,180,140],
60216  teal: [0,128,128],
60217  thistle:  [216,191,216],
60218  tomato: [255,99,71],
60219  turquoise:  [64,224,208],
60220  violet: [238,130,238],
60221  wheat:  [245,222,179],
60222  white:  [255,255,255],
60223  whitesmoke: [245,245,245],
60224  yellow: [255,255,0],
60225  yellowgreen:  [154,205,50]
60226};
60227
60228var reverseKeywords = {};
60229for (var key in cssKeywords) {
60230  reverseKeywords[JSON.stringify(cssKeywords[key])] = key;
60231}
60232
60233var convert = function() {
60234   return new Converter();
60235};
60236
60237for (var func in conversions) {
60238  // export Raw versions
60239  convert[func + "Raw"] =  (function(func) {
60240    // accept array or plain args
60241    return function(arg) {
60242      if (typeof arg == "number")
60243        arg = Array.prototype.slice.call(arguments);
60244      return conversions[func](arg);
60245    }
60246  })(func);
60247
60248  var pair = /(\w+)2(\w+)/.exec(func),
60249      from = pair[1],
60250      to = pair[2];
60251
60252  // export rgb2hsl and ["rgb"]["hsl"]
60253  convert[from] = convert[from] || {};
60254
60255  convert[from][to] = convert[func] = (function(func) { 
60256    return function(arg) {
60257      if (typeof arg == "number")
60258        arg = Array.prototype.slice.call(arguments);
60259      
60260      var val = conversions[func](arg);
60261      if (typeof val == "string" || val === undefined)
60262        return val; // keyword
60263
60264      for (var i = 0; i < val.length; i++)
60265        val[i] = Math.round(val[i]);
60266      return val;
60267    }
60268  })(func);
60269}
60270
60271
60272/* Converter does lazy conversion and caching */
60273var Converter = function() {
60274   this.convs = {};
60275};
60276
60277/* Either get the values for a space or
60278  set the values for a space, depending on args */
60279Converter.prototype.routeSpace = function(space, args) {
60280   var values = args[0];
60281   if (values === undefined) {
60282      // color.rgb()
60283      return this.getValues(space);
60284   }
60285   // color.rgb(10, 10, 10)
60286   if (typeof values == "number") {
60287      values = Array.prototype.slice.call(args);        
60288   }
60289
60290   return this.setValues(space, values);
60291};
60292  
60293/* Set the values for a space, invalidating cache */
60294Converter.prototype.setValues = function(space, values) {
60295   this.space = space;
60296   this.convs = {};
60297   this.convs[space] = values;
60298   return this;
60299};
60300
60301/* Get the values for a space. If there's already
60302  a conversion for the space, fetch it, otherwise
60303  compute it */
60304Converter.prototype.getValues = function(space) {
60305   var vals = this.convs[space];
60306   if (!vals) {
60307      var fspace = this.space,
60308          from = this.convs[fspace];
60309      vals = convert[fspace][space](from);
60310
60311      this.convs[space] = vals;
60312   }
60313  return vals;
60314};
60315
60316["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) {
60317   Converter.prototype[space] = function(vals) {
60318      return this.routeSpace(space, arguments);
60319   };
60320});
60321
60322var colorConvert = convert;
60323
60324var colorName = {
60325	"aliceblue": [240, 248, 255],
60326	"antiquewhite": [250, 235, 215],
60327	"aqua": [0, 255, 255],
60328	"aquamarine": [127, 255, 212],
60329	"azure": [240, 255, 255],
60330	"beige": [245, 245, 220],
60331	"bisque": [255, 228, 196],
60332	"black": [0, 0, 0],
60333	"blanchedalmond": [255, 235, 205],
60334	"blue": [0, 0, 255],
60335	"blueviolet": [138, 43, 226],
60336	"brown": [165, 42, 42],
60337	"burlywood": [222, 184, 135],
60338	"cadetblue": [95, 158, 160],
60339	"chartreuse": [127, 255, 0],
60340	"chocolate": [210, 105, 30],
60341	"coral": [255, 127, 80],
60342	"cornflowerblue": [100, 149, 237],
60343	"cornsilk": [255, 248, 220],
60344	"crimson": [220, 20, 60],
60345	"cyan": [0, 255, 255],
60346	"darkblue": [0, 0, 139],
vendor: 90,099 bytes, lines 60347-63954
60347	"darkcyan": [0, 139, 139],
60348	"darkgoldenrod": [184, 134, 11],
60349	"darkgray": [169, 169, 169],
60350	"darkgreen": [0, 100, 0],
60351	"darkgrey": [169, 169, 169],
60352	"darkkhaki": [189, 183, 107],
60353	"darkmagenta": [139, 0, 139],
60354	"darkolivegreen": [85, 107, 47],
60355	"darkorange": [255, 140, 0],
60356	"darkorchid": [153, 50, 204],
60357	"darkred": [139, 0, 0],
60358	"darksalmon": [233, 150, 122],
60359	"darkseagreen": [143, 188, 143],
60360	"darkslateblue": [72, 61, 139],
60361	"darkslategray": [47, 79, 79],
60362	"darkslategrey": [47, 79, 79],
60363	"darkturquoise": [0, 206, 209],
60364	"darkviolet": [148, 0, 211],
60365	"deeppink": [255, 20, 147],
60366	"deepskyblue": [0, 191, 255],
60367	"dimgray": [105, 105, 105],
60368	"dimgrey": [105, 105, 105],
60369	"dodgerblue": [30, 144, 255],
60370	"firebrick": [178, 34, 34],
60371	"floralwhite": [255, 250, 240],
60372	"forestgreen": [34, 139, 34],
60373	"fuchsia": [255, 0, 255],
60374	"gainsboro": [220, 220, 220],
60375	"ghostwhite": [248, 248, 255],
60376	"gold": [255, 215, 0],
60377	"goldenrod": [218, 165, 32],
60378	"gray": [128, 128, 128],
60379	"green": [0, 128, 0],
60380	"greenyellow": [173, 255, 47],
60381	"grey": [128, 128, 128],
60382	"honeydew": [240, 255, 240],
60383	"hotpink": [255, 105, 180],
60384	"indianred": [205, 92, 92],
60385	"indigo": [75, 0, 130],
60386	"ivory": [255, 255, 240],
60387	"khaki": [240, 230, 140],
60388	"lavender": [230, 230, 250],
60389	"lavenderblush": [255, 240, 245],
60390	"lawngreen": [124, 252, 0],
60391	"lemonchiffon": [255, 250, 205],
60392	"lightblue": [173, 216, 230],
60393	"lightcoral": [240, 128, 128],
60394	"lightcyan": [224, 255, 255],
60395	"lightgoldenrodyellow": [250, 250, 210],
60396	"lightgray": [211, 211, 211],
60397	"lightgreen": [144, 238, 144],
60398	"lightgrey": [211, 211, 211],
60399	"lightpink": [255, 182, 193],
60400	"lightsalmon": [255, 160, 122],
60401	"lightseagreen": [32, 178, 170],
60402	"lightskyblue": [135, 206, 250],
60403	"lightslategray": [119, 136, 153],
60404	"lightslategrey": [119, 136, 153],
60405	"lightsteelblue": [176, 196, 222],
60406	"lightyellow": [255, 255, 224],
60407	"lime": [0, 255, 0],
60408	"limegreen": [50, 205, 50],
60409	"linen": [250, 240, 230],
60410	"magenta": [255, 0, 255],
60411	"maroon": [128, 0, 0],
60412	"mediumaquamarine": [102, 205, 170],
60413	"mediumblue": [0, 0, 205],
60414	"mediumorchid": [186, 85, 211],
60415	"mediumpurple": [147, 112, 219],
60416	"mediumseagreen": [60, 179, 113],
60417	"mediumslateblue": [123, 104, 238],
60418	"mediumspringgreen": [0, 250, 154],
60419	"mediumturquoise": [72, 209, 204],
60420	"mediumvioletred": [199, 21, 133],
60421	"midnightblue": [25, 25, 112],
60422	"mintcream": [245, 255, 250],
60423	"mistyrose": [255, 228, 225],
60424	"moccasin": [255, 228, 181],
60425	"navajowhite": [255, 222, 173],
60426	"navy": [0, 0, 128],
60427	"oldlace": [253, 245, 230],
60428	"olive": [128, 128, 0],
60429	"olivedrab": [107, 142, 35],
60430	"orange": [255, 165, 0],
60431	"orangered": [255, 69, 0],
60432	"orchid": [218, 112, 214],
60433	"palegoldenrod": [238, 232, 170],
60434	"palegreen": [152, 251, 152],
60435	"paleturquoise": [175, 238, 238],
60436	"palevioletred": [219, 112, 147],
60437	"papayawhip": [255, 239, 213],
60438	"peachpuff": [255, 218, 185],
60439	"peru": [205, 133, 63],
60440	"pink": [255, 192, 203],
60441	"plum": [221, 160, 221],
60442	"powderblue": [176, 224, 230],
60443	"purple": [128, 0, 128],
60444	"rebeccapurple": [102, 51, 153],
60445	"red": [255, 0, 0],
60446	"rosybrown": [188, 143, 143],
60447	"royalblue": [65, 105, 225],
60448	"saddlebrown": [139, 69, 19],
60449	"salmon": [250, 128, 114],
60450	"sandybrown": [244, 164, 96],
60451	"seagreen": [46, 139, 87],
60452	"seashell": [255, 245, 238],
60453	"sienna": [160, 82, 45],
60454	"silver": [192, 192, 192],
60455	"skyblue": [135, 206, 235],
60456	"slateblue": [106, 90, 205],
60457	"slategray": [112, 128, 144],
60458	"slategrey": [112, 128, 144],
60459	"snow": [255, 250, 250],
60460	"springgreen": [0, 255, 127],
60461	"steelblue": [70, 130, 180],
60462	"tan": [210, 180, 140],
60463	"teal": [0, 128, 128],
60464	"thistle": [216, 191, 216],
60465	"tomato": [255, 99, 71],
60466	"turquoise": [64, 224, 208],
60467	"violet": [238, 130, 238],
60468	"wheat": [245, 222, 179],
60469	"white": [255, 255, 255],
60470	"whitesmoke": [245, 245, 245],
60471	"yellow": [255, 255, 0],
60472	"yellowgreen": [154, 205, 50]
60473};
60474
60475/* MIT license */
60476
60477
60478var colorString = {
60479   getRgba: getRgba,
60480   getHsla: getHsla,
60481   getRgb: getRgb,
60482   getHsl: getHsl,
60483   getHwb: getHwb,
60484   getAlpha: getAlpha,
60485
60486   hexString: hexString,
60487   rgbString: rgbString,
60488   rgbaString: rgbaString,
60489   percentString: percentString,
60490   percentaString: percentaString,
60491   hslString: hslString,
60492   hslaString: hslaString,
60493   hwbString: hwbString,
60494   keyword: keyword
60495};
60496
60497function getRgba(string) {
60498   if (!string) {
60499      return;
60500   }
60501   var abbr =  /^#([a-fA-F0-9]{3,4})$/i,
60502       hex =  /^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i,
60503       rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,
60504       per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,
60505       keyword = /(\w+)/;
60506
60507   var rgb = [0, 0, 0],
60508       a = 1,
60509       match = string.match(abbr),
60510       hexAlpha = "";
60511   if (match) {
60512      match = match[1];
60513      hexAlpha = match[3];
60514      for (var i = 0; i < rgb.length; i++) {
60515         rgb[i] = parseInt(match[i] + match[i], 16);
60516      }
60517      if (hexAlpha) {
60518         a = Math.round((parseInt(hexAlpha + hexAlpha, 16) / 255) * 100) / 100;
60519      }
60520   }
60521   else if (match = string.match(hex)) {
60522      hexAlpha = match[2];
60523      match = match[1];
60524      for (var i = 0; i < rgb.length; i++) {
60525         rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);
60526      }
60527      if (hexAlpha) {
60528         a = Math.round((parseInt(hexAlpha, 16) / 255) * 100) / 100;
60529      }
60530   }
60531   else if (match = string.match(rgba)) {
60532      for (var i = 0; i < rgb.length; i++) {
60533         rgb[i] = parseInt(match[i + 1]);
60534      }
60535      a = parseFloat(match[4]);
60536   }
60537   else if (match = string.match(per)) {
60538      for (var i = 0; i < rgb.length; i++) {
60539         rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);
60540      }
60541      a = parseFloat(match[4]);
60542   }
60543   else if (match = string.match(keyword)) {
60544      if (match[1] == "transparent") {
60545         return [0, 0, 0, 0];
60546      }
60547      rgb = colorName[match[1]];
60548      if (!rgb) {
60549         return;
60550      }
60551   }
60552
60553   for (var i = 0; i < rgb.length; i++) {
60554      rgb[i] = scale(rgb[i], 0, 255);
60555   }
60556   if (!a && a != 0) {
60557      a = 1;
60558   }
60559   else {
60560      a = scale(a, 0, 1);
60561   }
60562   rgb[3] = a;
60563   return rgb;
60564}
60565
60566function getHsla(string) {
60567   if (!string) {
60568      return;
60569   }
60570   var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
60571   var match = string.match(hsl);
60572   if (match) {
60573      var alpha = parseFloat(match[4]);
60574      var h = scale(parseInt(match[1]), 0, 360),
60575          s = scale(parseFloat(match[2]), 0, 100),
60576          l = scale(parseFloat(match[3]), 0, 100),
60577          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
60578      return [h, s, l, a];
60579   }
60580}
60581
60582function getHwb(string) {
60583   if (!string) {
60584      return;
60585   }
60586   var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
60587   var match = string.match(hwb);
60588   if (match) {
60589    var alpha = parseFloat(match[4]);
60590      var h = scale(parseInt(match[1]), 0, 360),
60591          w = scale(parseFloat(match[2]), 0, 100),
60592          b = scale(parseFloat(match[3]), 0, 100),
60593          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
60594      return [h, w, b, a];
60595   }
60596}
60597
60598function getRgb(string) {
60599   var rgba = getRgba(string);
60600   return rgba && rgba.slice(0, 3);
60601}
60602
60603function getHsl(string) {
60604  var hsla = getHsla(string);
60605  return hsla && hsla.slice(0, 3);
60606}
60607
60608function getAlpha(string) {
60609   var vals = getRgba(string);
60610   if (vals) {
60611      return vals[3];
60612   }
60613   else if (vals = getHsla(string)) {
60614      return vals[3];
60615   }
60616   else if (vals = getHwb(string)) {
60617      return vals[3];
60618   }
60619}
60620
60621// generators
60622function hexString(rgba, a) {
60623   var a = (a !== undefined && rgba.length === 3) ? a : rgba[3];
60624   return "#" + hexDouble(rgba[0]) 
60625              + hexDouble(rgba[1])
60626              + hexDouble(rgba[2])
60627              + (
60628                 (a >= 0 && a < 1)
60629                 ? hexDouble(Math.round(a * 255))
60630                 : ""
60631              );
60632}
60633
60634function rgbString(rgba, alpha) {
60635   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
60636      return rgbaString(rgba, alpha);
60637   }
60638   return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")";
60639}
60640
60641function rgbaString(rgba, alpha) {
60642   if (alpha === undefined) {
60643      alpha = (rgba[3] !== undefined ? rgba[3] : 1);
60644   }
60645   return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2]
60646           + ", " + alpha + ")";
60647}
60648
60649function percentString(rgba, alpha) {
60650   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
60651      return percentaString(rgba, alpha);
60652   }
60653   var r = Math.round(rgba[0]/255 * 100),
60654       g = Math.round(rgba[1]/255 * 100),
60655       b = Math.round(rgba[2]/255 * 100);
60656
60657   return "rgb(" + r + "%, " + g + "%, " + b + "%)";
60658}
60659
60660function percentaString(rgba, alpha) {
60661   var r = Math.round(rgba[0]/255 * 100),
60662       g = Math.round(rgba[1]/255 * 100),
60663       b = Math.round(rgba[2]/255 * 100);
60664   return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")";
60665}
60666
60667function hslString(hsla, alpha) {
60668   if (alpha < 1 || (hsla[3] && hsla[3] < 1)) {
60669      return hslaString(hsla, alpha);
60670   }
60671   return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";
60672}
60673
60674function hslaString(hsla, alpha) {
60675   if (alpha === undefined) {
60676      alpha = (hsla[3] !== undefined ? hsla[3] : 1);
60677   }
60678   return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, "
60679           + alpha + ")";
60680}
60681
60682// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax
60683// (hwb have alpha optional & 1 is default value)
60684function hwbString(hwb, alpha) {
60685   if (alpha === undefined) {
60686      alpha = (hwb[3] !== undefined ? hwb[3] : 1);
60687   }
60688   return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%"
60689           + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")";
60690}
60691
60692function keyword(rgb) {
60693  return reverseNames[rgb.slice(0, 3)];
60694}
60695
60696// helpers
60697function scale(num, min, max) {
60698   return Math.min(Math.max(min, num), max);
60699}
60700
60701function hexDouble(num) {
60702  var str = num.toString(16).toUpperCase();
60703  return (str.length < 2) ? "0" + str : str;
60704}
60705
60706
60707//create a list of reverse color names
60708var reverseNames = {};
60709for (var name in colorName) {
60710   reverseNames[colorName[name]] = name;
60711}
60712
60713/* MIT license */
60714
60715
60716
60717var Color = function (obj) {
60718	if (obj instanceof Color) {
60719		return obj;
60720	}
60721	if (!(this instanceof Color)) {
60722		return new Color(obj);
60723	}
60724
60725	this.valid = false;
60726	this.values = {
60727		rgb: [0, 0, 0],
60728		hsl: [0, 0, 0],
60729		hsv: [0, 0, 0],
60730		hwb: [0, 0, 0],
60731		cmyk: [0, 0, 0, 0],
60732		alpha: 1
60733	};
60734
60735	// parse Color() argument
60736	var vals;
60737	if (typeof obj === 'string') {
60738		vals = colorString.getRgba(obj);
60739		if (vals) {
60740			this.setValues('rgb', vals);
60741		} else if (vals = colorString.getHsla(obj)) {
60742			this.setValues('hsl', vals);
60743		} else if (vals = colorString.getHwb(obj)) {
60744			this.setValues('hwb', vals);
60745		}
60746	} else if (typeof obj === 'object') {
60747		vals = obj;
60748		if (vals.r !== undefined || vals.red !== undefined) {
60749			this.setValues('rgb', vals);
60750		} else if (vals.l !== undefined || vals.lightness !== undefined) {
60751			this.setValues('hsl', vals);
60752		} else if (vals.v !== undefined || vals.value !== undefined) {
60753			this.setValues('hsv', vals);
60754		} else if (vals.w !== undefined || vals.whiteness !== undefined) {
60755			this.setValues('hwb', vals);
60756		} else if (vals.c !== undefined || vals.cyan !== undefined) {
60757			this.setValues('cmyk', vals);
60758		}
60759	}
60760};
60761
60762Color.prototype = {
60763	isValid: function () {
60764		return this.valid;
60765	},
60766	rgb: function () {
60767		return this.setSpace('rgb', arguments);
60768	},
60769	hsl: function () {
60770		return this.setSpace('hsl', arguments);
60771	},
60772	hsv: function () {
60773		return this.setSpace('hsv', arguments);
60774	},
60775	hwb: function () {
60776		return this.setSpace('hwb', arguments);
60777	},
60778	cmyk: function () {
60779		return this.setSpace('cmyk', arguments);
60780	},
60781
60782	rgbArray: function () {
60783		return this.values.rgb;
60784	},
60785	hslArray: function () {
60786		return this.values.hsl;
60787	},
60788	hsvArray: function () {
60789		return this.values.hsv;
60790	},
60791	hwbArray: function () {
60792		var values = this.values;
60793		if (values.alpha !== 1) {
60794			return values.hwb.concat([values.alpha]);
60795		}
60796		return values.hwb;
60797	},
60798	cmykArray: function () {
60799		return this.values.cmyk;
60800	},
60801	rgbaArray: function () {
60802		var values = this.values;
60803		return values.rgb.concat([values.alpha]);
60804	},
60805	hslaArray: function () {
60806		var values = this.values;
60807		return values.hsl.concat([values.alpha]);
60808	},
60809	alpha: function (val) {
60810		if (val === undefined) {
60811			return this.values.alpha;
60812		}
60813		this.setValues('alpha', val);
60814		return this;
60815	},
60816
60817	red: function (val) {
60818		return this.setChannel('rgb', 0, val);
60819	},
60820	green: function (val) {
60821		return this.setChannel('rgb', 1, val);
60822	},
60823	blue: function (val) {
60824		return this.setChannel('rgb', 2, val);
60825	},
60826	hue: function (val) {
60827		if (val) {
60828			val %= 360;
60829			val = val < 0 ? 360 + val : val;
60830		}
60831		return this.setChannel('hsl', 0, val);
60832	},
60833	saturation: function (val) {
60834		return this.setChannel('hsl', 1, val);
60835	},
60836	lightness: function (val) {
60837		return this.setChannel('hsl', 2, val);
60838	},
60839	saturationv: function (val) {
60840		return this.setChannel('hsv', 1, val);
60841	},
60842	whiteness: function (val) {
60843		return this.setChannel('hwb', 1, val);
60844	},
60845	blackness: function (val) {
60846		return this.setChannel('hwb', 2, val);
60847	},
60848	value: function (val) {
60849		return this.setChannel('hsv', 2, val);
60850	},
60851	cyan: function (val) {
60852		return this.setChannel('cmyk', 0, val);
60853	},
60854	magenta: function (val) {
60855		return this.setChannel('cmyk', 1, val);
60856	},
60857	yellow: function (val) {
60858		return this.setChannel('cmyk', 2, val);
60859	},
60860	black: function (val) {
60861		return this.setChannel('cmyk', 3, val);
60862	},
60863
60864	hexString: function () {
60865		return colorString.hexString(this.values.rgb);
60866	},
60867	rgbString: function () {
60868		return colorString.rgbString(this.values.rgb, this.values.alpha);
60869	},
60870	rgbaString: function () {
60871		return colorString.rgbaString(this.values.rgb, this.values.alpha);
60872	},
60873	percentString: function () {
60874		return colorString.percentString(this.values.rgb, this.values.alpha);
60875	},
60876	hslString: function () {
60877		return colorString.hslString(this.values.hsl, this.values.alpha);
60878	},
60879	hslaString: function () {
60880		return colorString.hslaString(this.values.hsl, this.values.alpha);
60881	},
60882	hwbString: function () {
60883		return colorString.hwbString(this.values.hwb, this.values.alpha);
60884	},
60885	keyword: function () {
60886		return colorString.keyword(this.values.rgb, this.values.alpha);
60887	},
60888
60889	rgbNumber: function () {
60890		var rgb = this.values.rgb;
60891		return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
60892	},
60893
60894	luminosity: function () {
60895		// http://www.w3.org/TR/WCAG20/#relativeluminancedef
60896		var rgb = this.values.rgb;
60897		var lum = [];
60898		for (var i = 0; i < rgb.length; i++) {
60899			var chan = rgb[i] / 255;
60900			lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4);
60901		}
60902		return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];
60903	},
60904
60905	contrast: function (color2) {
60906		// http://www.w3.org/TR/WCAG20/#contrast-ratiodef
60907		var lum1 = this.luminosity();
60908		var lum2 = color2.luminosity();
60909		if (lum1 > lum2) {
60910			return (lum1 + 0.05) / (lum2 + 0.05);
60911		}
60912		return (lum2 + 0.05) / (lum1 + 0.05);
60913	},
60914
60915	level: function (color2) {
60916		var contrastRatio = this.contrast(color2);
60917		if (contrastRatio >= 7.1) {
60918			return 'AAA';
60919		}
60920
60921		return (contrastRatio >= 4.5) ? 'AA' : '';
60922	},
60923
60924	dark: function () {
60925		// YIQ equation from http://24ways.org/2010/calculating-color-contrast
60926		var rgb = this.values.rgb;
60927		var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
60928		return yiq < 128;
60929	},
60930
60931	light: function () {
60932		return !this.dark();
60933	},
60934
60935	negate: function () {
60936		var rgb = [];
60937		for (var i = 0; i < 3; i++) {
60938			rgb[i] = 255 - this.values.rgb[i];
60939		}
60940		this.setValues('rgb', rgb);
60941		return this;
60942	},
60943
60944	lighten: function (ratio) {
60945		var hsl = this.values.hsl;
60946		hsl[2] += hsl[2] * ratio;
60947		this.setValues('hsl', hsl);
60948		return this;
60949	},
60950
60951	darken: function (ratio) {
60952		var hsl = this.values.hsl;
60953		hsl[2] -= hsl[2] * ratio;
60954		this.setValues('hsl', hsl);
60955		return this;
60956	},
60957
60958	saturate: function (ratio) {
60959		var hsl = this.values.hsl;
60960		hsl[1] += hsl[1] * ratio;
60961		this.setValues('hsl', hsl);
60962		return this;
60963	},
60964
60965	desaturate: function (ratio) {
60966		var hsl = this.values.hsl;
60967		hsl[1] -= hsl[1] * ratio;
60968		this.setValues('hsl', hsl);
60969		return this;
60970	},
60971
60972	whiten: function (ratio) {
60973		var hwb = this.values.hwb;
60974		hwb[1] += hwb[1] * ratio;
60975		this.setValues('hwb', hwb);
60976		return this;
60977	},
60978
60979	blacken: function (ratio) {
60980		var hwb = this.values.hwb;
60981		hwb[2] += hwb[2] * ratio;
60982		this.setValues('hwb', hwb);
60983		return this;
60984	},
60985
60986	greyscale: function () {
60987		var rgb = this.values.rgb;
60988		// http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
60989		var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;
60990		this.setValues('rgb', [val, val, val]);
60991		return this;
60992	},
60993
60994	clearer: function (ratio) {
60995		var alpha = this.values.alpha;
60996		this.setValues('alpha', alpha - (alpha * ratio));
60997		return this;
60998	},
60999
61000	opaquer: function (ratio) {
61001		var alpha = this.values.alpha;
61002		this.setValues('alpha', alpha + (alpha * ratio));
61003		return this;
61004	},
61005
61006	rotate: function (degrees) {
61007		var hsl = this.values.hsl;
61008		var hue = (hsl[0] + degrees) % 360;
61009		hsl[0] = hue < 0 ? 360 + hue : hue;
61010		this.setValues('hsl', hsl);
61011		return this;
61012	},
61013
61014	/**
61015	 * Ported from sass implementation in C
61016	 * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209
61017	 */
61018	mix: function (mixinColor, weight) {
61019		var color1 = this;
61020		var color2 = mixinColor;
61021		var p = weight === undefined ? 0.5 : weight;
61022
61023		var w = 2 * p - 1;
61024		var a = color1.alpha() - color2.alpha();
61025
61026		var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
61027		var w2 = 1 - w1;
61028
61029		return this
61030			.rgb(
61031				w1 * color1.red() + w2 * color2.red(),
61032				w1 * color1.green() + w2 * color2.green(),
61033				w1 * color1.blue() + w2 * color2.blue()
61034			)
61035			.alpha(color1.alpha() * p + color2.alpha() * (1 - p));
61036	},
61037
61038	toJSON: function () {
61039		return this.rgb();
61040	},
61041
61042	clone: function () {
61043		// NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,
61044		// making the final build way to big to embed in Chart.js. So let's do it manually,
61045		// assuming that values to clone are 1 dimension arrays containing only numbers,
61046		// except 'alpha' which is a number.
61047		var result = new Color();
61048		var source = this.values;
61049		var target = result.values;
61050		var value, type;
61051
61052		for (var prop in source) {
61053			if (source.hasOwnProperty(prop)) {
61054				value = source[prop];
61055				type = ({}).toString.call(value);
61056				if (type === '[object Array]') {
61057					target[prop] = value.slice(0);
61058				} else if (type === '[object Number]') {
61059					target[prop] = value;
61060				} else {
61061					console.error('unexpected color value:', value);
61062				}
61063			}
61064		}
61065
61066		return result;
61067	}
61068};
61069
61070Color.prototype.spaces = {
61071	rgb: ['red', 'green', 'blue'],
61072	hsl: ['hue', 'saturation', 'lightness'],
61073	hsv: ['hue', 'saturation', 'value'],
61074	hwb: ['hue', 'whiteness', 'blackness'],
61075	cmyk: ['cyan', 'magenta', 'yellow', 'black']
61076};
61077
61078Color.prototype.maxes = {
61079	rgb: [255, 255, 255],
61080	hsl: [360, 100, 100],
61081	hsv: [360, 100, 100],
61082	hwb: [360, 100, 100],
61083	cmyk: [100, 100, 100, 100]
61084};
61085
61086Color.prototype.getValues = function (space) {
61087	var values = this.values;
61088	var vals = {};
61089
61090	for (var i = 0; i < space.length; i++) {
61091		vals[space.charAt(i)] = values[space][i];
61092	}
61093
61094	if (values.alpha !== 1) {
61095		vals.a = values.alpha;
61096	}
61097
61098	// {r: 255, g: 255, b: 255, a: 0.4}
61099	return vals;
61100};
61101
61102Color.prototype.setValues = function (space, vals) {
61103	var values = this.values;
61104	var spaces = this.spaces;
61105	var maxes = this.maxes;
61106	var alpha = 1;
61107	var i;
61108
61109	this.valid = true;
61110
61111	if (space === 'alpha') {
61112		alpha = vals;
61113	} else if (vals.length) {
61114		// [10, 10, 10]
61115		values[space] = vals.slice(0, space.length);
61116		alpha = vals[space.length];
61117	} else if (vals[space.charAt(0)] !== undefined) {
61118		// {r: 10, g: 10, b: 10}
61119		for (i = 0; i < space.length; i++) {
61120			values[space][i] = vals[space.charAt(i)];
61121		}
61122
61123		alpha = vals.a;
61124	} else if (vals[spaces[space][0]] !== undefined) {
61125		// {red: 10, green: 10, blue: 10}
61126		var chans = spaces[space];
61127
61128		for (i = 0; i < space.length; i++) {
61129			values[space][i] = vals[chans[i]];
61130		}
61131
61132		alpha = vals.alpha;
61133	}
61134
61135	values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha)));
61136
61137	if (space === 'alpha') {
61138		return false;
61139	}
61140
61141	var capped;
61142
61143	// cap values of the space prior converting all values
61144	for (i = 0; i < space.length; i++) {
61145		capped = Math.max(0, Math.min(maxes[space][i], values[space][i]));
61146		values[space][i] = Math.round(capped);
61147	}
61148
61149	// convert to all the other color spaces
61150	for (var sname in spaces) {
61151		if (sname !== space) {
61152			values[sname] = colorConvert[space][sname](values[space]);
61153		}
61154	}
61155
61156	return true;
61157};
61158
61159Color.prototype.setSpace = function (space, args) {
61160	var vals = args[0];
61161
61162	if (vals === undefined) {
61163		// color.rgb()
61164		return this.getValues(space);
61165	}
61166
61167	// color.rgb(10, 10, 10)
61168	if (typeof vals === 'number') {
61169		vals = Array.prototype.slice.call(args);
61170	}
61171
61172	this.setValues(space, vals);
61173	return this;
61174};
61175
61176Color.prototype.setChannel = function (space, index, val) {
61177	var svalues = this.values[space];
61178	if (val === undefined) {
61179		// color.red()
61180		return svalues[index];
61181	} else if (val === svalues[index]) {
61182		// color.red(color.red())
61183		return this;
61184	}
61185
61186	// color.red(100)
61187	svalues[index] = val;
61188	this.setValues(space, svalues);
61189
61190	return this;
61191};
61192
61193if (typeof window !== 'undefined') {
61194	window.Color = Color;
61195}
61196
61197var chartjsColor = Color;
61198
61199/**
61200 * @namespace Chart.helpers
61201 */
61202var helpers = {
61203	/**
61204	 * An empty function that can be used, for example, for optional callback.
61205	 */
61206	noop: function() {},
61207
61208	/**
61209	 * Returns a unique id, sequentially generated from a global variable.
61210	 * @returns {number}
61211	 * @function
61212	 */
61213	uid: (function() {
61214		var id = 0;
61215		return function() {
61216			return id++;
61217		};
61218	}()),
61219
61220	/**
61221	 * Returns true if `value` is neither null nor undefined, else returns false.
61222	 * @param {*} value - The value to test.
61223	 * @returns {boolean}
61224	 * @since 2.7.0
61225	 */
61226	isNullOrUndef: function(value) {
61227		return value === null || typeof value === 'undefined';
61228	},
61229
61230	/**
61231	 * Returns true if `value` is an array (including typed arrays), else returns false.
61232	 * @param {*} value - The value to test.
61233	 * @returns {boolean}
61234	 * @function
61235	 */
61236	isArray: function(value) {
61237		if (Array.isArray && Array.isArray(value)) {
61238			return true;
61239		}
61240		var type = Object.prototype.toString.call(value);
61241		if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') {
61242			return true;
61243		}
61244		return false;
61245	},
61246
61247	/**
61248	 * Returns true if `value` is an object (excluding null), else returns false.
61249	 * @param {*} value - The value to test.
61250	 * @returns {boolean}
61251	 * @since 2.7.0
61252	 */
61253	isObject: function(value) {
61254		return value !== null && Object.prototype.toString.call(value) === '[object Object]';
61255	},
61256
61257	/**
61258	 * Returns true if `value` is a finite number, else returns false
61259	 * @param {*} value  - The value to test.
61260	 * @returns {boolean}
61261	 */
61262	isFinite: function(value) {
61263		return (typeof value === 'number' || value instanceof Number) && isFinite(value);
61264	},
61265
61266	/**
61267	 * Returns `value` if defined, else returns `defaultValue`.
61268	 * @param {*} value - The value to return if defined.
61269	 * @param {*} defaultValue - The value to return if `value` is undefined.
61270	 * @returns {*}
61271	 */
61272	valueOrDefault: function(value, defaultValue) {
61273		return typeof value === 'undefined' ? defaultValue : value;
61274	},
61275
61276	/**
61277	 * Returns value at the given `index` in array if defined, else returns `defaultValue`.
61278	 * @param {Array} value - The array to lookup for value at `index`.
61279	 * @param {number} index - The index in `value` to lookup for value.
61280	 * @param {*} defaultValue - The value to return if `value[index]` is undefined.
61281	 * @returns {*}
61282	 */
61283	valueAtIndexOrDefault: function(value, index, defaultValue) {
61284		return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue);
61285	},
61286
61287	/**
61288	 * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the
61289	 * value returned by `fn`. If `fn` is not a function, this method returns undefined.
61290	 * @param {function} fn - The function to call.
61291	 * @param {Array|undefined|null} args - The arguments with which `fn` should be called.
61292	 * @param {object} [thisArg] - The value of `this` provided for the call to `fn`.
61293	 * @returns {*}
61294	 */
61295	callback: function(fn, args, thisArg) {
61296		if (fn && typeof fn.call === 'function') {
61297			return fn.apply(thisArg, args);
61298		}
61299	},
61300
61301	/**
61302	 * Note(SB) for performance sake, this method should only be used when loopable type
61303	 * is unknown or in none intensive code (not called often and small loopable). Else
61304	 * it's preferable to use a regular for() loop and save extra function calls.
61305	 * @param {object|Array} loopable - The object or array to be iterated.
61306	 * @param {function} fn - The function to call for each item.
61307	 * @param {object} [thisArg] - The value of `this` provided for the call to `fn`.
61308	 * @param {boolean} [reverse] - If true, iterates backward on the loopable.
61309	 */
61310	each: function(loopable, fn, thisArg, reverse) {
61311		var i, len, keys;
61312		if (helpers.isArray(loopable)) {
61313			len = loopable.length;
61314			if (reverse) {
61315				for (i = len - 1; i >= 0; i--) {
61316					fn.call(thisArg, loopable[i], i);
61317				}
61318			} else {
61319				for (i = 0; i < len; i++) {
61320					fn.call(thisArg, loopable[i], i);
61321				}
61322			}
61323		} else if (helpers.isObject(loopable)) {
61324			keys = Object.keys(loopable);
61325			len = keys.length;
61326			for (i = 0; i < len; i++) {
61327				fn.call(thisArg, loopable[keys[i]], keys[i]);
61328			}
61329		}
61330	},
61331
61332	/**
61333	 * Returns true if the `a0` and `a1` arrays have the same content, else returns false.
61334	 * @see https://stackoverflow.com/a/14853974
61335	 * @param {Array} a0 - The array to compare
61336	 * @param {Array} a1 - The array to compare
61337	 * @returns {boolean}
61338	 */
61339	arrayEquals: function(a0, a1) {
61340		var i, ilen, v0, v1;
61341
61342		if (!a0 || !a1 || a0.length !== a1.length) {
61343			return false;
61344		}
61345
61346		for (i = 0, ilen = a0.length; i < ilen; ++i) {
61347			v0 = a0[i];
61348			v1 = a1[i];
61349
61350			if (v0 instanceof Array && v1 instanceof Array) {
61351				if (!helpers.arrayEquals(v0, v1)) {
61352					return false;
61353				}
61354			} else if (v0 !== v1) {
61355				// NOTE: two different object instances will never be equal: {x:20} != {x:20}
61356				return false;
61357			}
61358		}
61359
61360		return true;
61361	},
61362
61363	/**
61364	 * Returns a deep copy of `source` without keeping references on objects and arrays.
61365	 * @param {*} source - The value to clone.
61366	 * @returns {*}
61367	 */
61368	clone: function(source) {
61369		if (helpers.isArray(source)) {
61370			return source.map(helpers.clone);
61371		}
61372
61373		if (helpers.isObject(source)) {
61374			var target = {};
61375			var keys = Object.keys(source);
61376			var klen = keys.length;
61377			var k = 0;
61378
61379			for (; k < klen; ++k) {
61380				target[keys[k]] = helpers.clone(source[keys[k]]);
61381			}
61382
61383			return target;
61384		}
61385
61386		return source;
61387	},
61388
61389	/**
61390	 * The default merger when Chart.helpers.merge is called without merger option.
61391	 * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback.
61392	 * @private
61393	 */
61394	_merger: function(key, target, source, options) {
61395		var tval = target[key];
61396		var sval = source[key];
61397
61398		if (helpers.isObject(tval) && helpers.isObject(sval)) {
61399			helpers.merge(tval, sval, options);
61400		} else {
61401			target[key] = helpers.clone(sval);
61402		}
61403	},
61404
61405	/**
61406	 * Merges source[key] in target[key] only if target[key] is undefined.
61407	 * @private
61408	 */
61409	_mergerIf: function(key, target, source) {
61410		var tval = target[key];
61411		var sval = source[key];
61412
61413		if (helpers.isObject(tval) && helpers.isObject(sval)) {
61414			helpers.mergeIf(tval, sval);
61415		} else if (!target.hasOwnProperty(key)) {
61416			target[key] = helpers.clone(sval);
61417		}
61418	},
61419
61420	/**
61421	 * Recursively deep copies `source` properties into `target` with the given `options`.
61422	 * IMPORTANT: `target` is not cloned and will be updated with `source` properties.
61423	 * @param {object} target - The target object in which all sources are merged into.
61424	 * @param {object|object[]} source - Object(s) to merge into `target`.
61425	 * @param {object} [options] - Merging options:
61426	 * @param {function} [options.merger] - The merge method (key, target, source, options)
61427	 * @returns {object} The `target` object.
61428	 */
61429	merge: function(target, source, options) {
61430		var sources = helpers.isArray(source) ? source : [source];
61431		var ilen = sources.length;
61432		var merge, i, keys, klen, k;
61433
61434		if (!helpers.isObject(target)) {
61435			return target;
61436		}
61437
61438		options = options || {};
61439		merge = options.merger || helpers._merger;
61440
61441		for (i = 0; i < ilen; ++i) {
61442			source = sources[i];
61443			if (!helpers.isObject(source)) {
61444				continue;
61445			}
61446
61447			keys = Object.keys(source);
61448			for (k = 0, klen = keys.length; k < klen; ++k) {
61449				merge(keys[k], target, source, options);
61450			}
61451		}
61452
61453		return target;
61454	},
61455
61456	/**
61457	 * Recursively deep copies `source` properties into `target` *only* if not defined in target.
61458	 * IMPORTANT: `target` is not cloned and will be updated with `source` properties.
61459	 * @param {object} target - The target object in which all sources are merged into.
61460	 * @param {object|object[]} source - Object(s) to merge into `target`.
61461	 * @returns {object} The `target` object.
61462	 */
61463	mergeIf: function(target, source) {
61464		return helpers.merge(target, source, {merger: helpers._mergerIf});
61465	},
61466
61467	/**
61468	 * Applies the contents of two or more objects together into the first object.
61469	 * @param {object} target - The target object in which all objects are merged into.
61470	 * @param {object} arg1 - Object containing additional properties to merge in target.
61471	 * @param {object} argN - Additional objects containing properties to merge in target.
61472	 * @returns {object} The `target` object.
61473	 */
61474	extend: function(target) {
61475		var setFn = function(value, key) {
61476			target[key] = value;
61477		};
61478		for (var i = 1, ilen = arguments.length; i < ilen; ++i) {
61479			helpers.each(arguments[i], setFn);
61480		}
61481		return target;
61482	},
61483
61484	/**
61485	 * Basic javascript inheritance based on the model created in Backbone.js
61486	 */
61487	inherits: function(extensions) {
61488		var me = this;
61489		var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() {
61490			return me.apply(this, arguments);
61491		};
61492
61493		var Surrogate = function() {
61494			this.constructor = ChartElement;
61495		};
61496
61497		Surrogate.prototype = me.prototype;
61498		ChartElement.prototype = new Surrogate();
61499		ChartElement.extend = helpers.inherits;
61500
61501		if (extensions) {
61502			helpers.extend(ChartElement.prototype, extensions);
61503		}
61504
61505		ChartElement.__super__ = me.prototype;
61506		return ChartElement;
61507	}
61508};
61509
61510var helpers_core = helpers;
61511
61512// DEPRECATIONS
61513
61514/**
61515 * Provided for backward compatibility, use Chart.helpers.callback instead.
61516 * @function Chart.helpers.callCallback
61517 * @deprecated since version 2.6.0
61518 * @todo remove at version 3
61519 * @private
61520 */
61521helpers.callCallback = helpers.callback;
61522
61523/**
61524 * Provided for backward compatibility, use Array.prototype.indexOf instead.
61525 * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+
61526 * @function Chart.helpers.indexOf
61527 * @deprecated since version 2.7.0
61528 * @todo remove at version 3
61529 * @private
61530 */
61531helpers.indexOf = function(array, item, fromIndex) {
61532	return Array.prototype.indexOf.call(array, item, fromIndex);
61533};
61534
61535/**
61536 * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead.
61537 * @function Chart.helpers.getValueOrDefault
61538 * @deprecated since version 2.7.0
61539 * @todo remove at version 3
61540 * @private
61541 */
61542helpers.getValueOrDefault = helpers.valueOrDefault;
61543
61544/**
61545 * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead.
61546 * @function Chart.helpers.getValueAtIndexOrDefault
61547 * @deprecated since version 2.7.0
61548 * @todo remove at version 3
61549 * @private
61550 */
61551helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
61552
61553/**
61554 * Easing functions adapted from Robert Penner's easing equations.
61555 * @namespace Chart.helpers.easingEffects
61556 * @see http://www.robertpenner.com/easing/
61557 */
61558var effects = {
61559	linear: function(t) {
61560		return t;
61561	},
61562
61563	easeInQuad: function(t) {
61564		return t * t;
61565	},
61566
61567	easeOutQuad: function(t) {
61568		return -t * (t - 2);
61569	},
61570
61571	easeInOutQuad: function(t) {
61572		if ((t /= 0.5) < 1) {
61573			return 0.5 * t * t;
61574		}
61575		return -0.5 * ((--t) * (t - 2) - 1);
61576	},
61577
61578	easeInCubic: function(t) {
61579		return t * t * t;
61580	},
61581
61582	easeOutCubic: function(t) {
61583		return (t = t - 1) * t * t + 1;
61584	},
61585
61586	easeInOutCubic: function(t) {
61587		if ((t /= 0.5) < 1) {
61588			return 0.5 * t * t * t;
61589		}
61590		return 0.5 * ((t -= 2) * t * t + 2);
61591	},
61592
61593	easeInQuart: function(t) {
61594		return t * t * t * t;
61595	},
61596
61597	easeOutQuart: function(t) {
61598		return -((t = t - 1) * t * t * t - 1);
61599	},
61600
61601	easeInOutQuart: function(t) {
61602		if ((t /= 0.5) < 1) {
61603			return 0.5 * t * t * t * t;
61604		}
61605		return -0.5 * ((t -= 2) * t * t * t - 2);
61606	},
61607
61608	easeInQuint: function(t) {
61609		return t * t * t * t * t;
61610	},
61611
61612	easeOutQuint: function(t) {
61613		return (t = t - 1) * t * t * t * t + 1;
61614	},
61615
61616	easeInOutQuint: function(t) {
61617		if ((t /= 0.5) < 1) {
61618			return 0.5 * t * t * t * t * t;
61619		}
61620		return 0.5 * ((t -= 2) * t * t * t * t + 2);
61621	},
61622
61623	easeInSine: function(t) {
61624		return -Math.cos(t * (Math.PI / 2)) + 1;
61625	},
61626
61627	easeOutSine: function(t) {
61628		return Math.sin(t * (Math.PI / 2));
61629	},
61630
61631	easeInOutSine: function(t) {
61632		return -0.5 * (Math.cos(Math.PI * t) - 1);
61633	},
61634
61635	easeInExpo: function(t) {
61636		return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
61637	},
61638
61639	easeOutExpo: function(t) {
61640		return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1;
61641	},
61642
61643	easeInOutExpo: function(t) {
61644		if (t === 0) {
61645			return 0;
61646		}
61647		if (t === 1) {
61648			return 1;
61649		}
61650		if ((t /= 0.5) < 1) {
61651			return 0.5 * Math.pow(2, 10 * (t - 1));
61652		}
61653		return 0.5 * (-Math.pow(2, -10 * --t) + 2);
61654	},
61655
61656	easeInCirc: function(t) {
61657		if (t >= 1) {
61658			return t;
61659		}
61660		return -(Math.sqrt(1 - t * t) - 1);
61661	},
61662
61663	easeOutCirc: function(t) {
61664		return Math.sqrt(1 - (t = t - 1) * t);
61665	},
61666
61667	easeInOutCirc: function(t) {
61668		if ((t /= 0.5) < 1) {
61669			return -0.5 * (Math.sqrt(1 - t * t) - 1);
61670		}
61671		return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
61672	},
61673
61674	easeInElastic: function(t) {
61675		var s = 1.70158;
61676		var p = 0;
61677		var a = 1;
61678		if (t === 0) {
61679			return 0;
61680		}
61681		if (t === 1) {
61682			return 1;
61683		}
61684		if (!p) {
61685			p = 0.3;
61686		}
61687		if (a < 1) {
61688			a = 1;
61689			s = p / 4;
61690		} else {
61691			s = p / (2 * Math.PI) * Math.asin(1 / a);
61692		}
61693		return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
61694	},
61695
61696	easeOutElastic: function(t) {
61697		var s = 1.70158;
61698		var p = 0;
61699		var a = 1;
61700		if (t === 0) {
61701			return 0;
61702		}
61703		if (t === 1) {
61704			return 1;
61705		}
61706		if (!p) {
61707			p = 0.3;
61708		}
61709		if (a < 1) {
61710			a = 1;
61711			s = p / 4;
61712		} else {
61713			s = p / (2 * Math.PI) * Math.asin(1 / a);
61714		}
61715		return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1;
61716	},
61717
61718	easeInOutElastic: function(t) {
61719		var s = 1.70158;
61720		var p = 0;
61721		var a = 1;
61722		if (t === 0) {
61723			return 0;
61724		}
61725		if ((t /= 0.5) === 2) {
61726			return 1;
61727		}
61728		if (!p) {
61729			p = 0.45;
61730		}
61731		if (a < 1) {
61732			a = 1;
61733			s = p / 4;
61734		} else {
61735			s = p / (2 * Math.PI) * Math.asin(1 / a);
61736		}
61737		if (t < 1) {
61738			return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
61739		}
61740		return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1;
61741	},
61742	easeInBack: function(t) {
61743		var s = 1.70158;
61744		return t * t * ((s + 1) * t - s);
61745	},
61746
61747	easeOutBack: function(t) {
61748		var s = 1.70158;
61749		return (t = t - 1) * t * ((s + 1) * t + s) + 1;
61750	},
61751
61752	easeInOutBack: function(t) {
61753		var s = 1.70158;
61754		if ((t /= 0.5) < 1) {
61755			return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s));
61756		}
61757		return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
61758	},
61759
61760	easeInBounce: function(t) {
61761		return 1 - effects.easeOutBounce(1 - t);
61762	},
61763
61764	easeOutBounce: function(t) {
61765		if (t < (1 / 2.75)) {
61766			return 7.5625 * t * t;
61767		}
61768		if (t < (2 / 2.75)) {
61769			return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75;
61770		}
61771		if (t < (2.5 / 2.75)) {
61772			return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375;
61773		}
61774		return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375;
61775	},
61776
61777	easeInOutBounce: function(t) {
61778		if (t < 0.5) {
61779			return effects.easeInBounce(t * 2) * 0.5;
61780		}
61781		return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5;
61782	}
61783};
61784
61785var helpers_easing = {
61786	effects: effects
61787};
61788
61789// DEPRECATIONS
61790
61791/**
61792 * Provided for backward compatibility, use Chart.helpers.easing.effects instead.
61793 * @function Chart.helpers.easingEffects
61794 * @deprecated since version 2.7.0
61795 * @todo remove at version 3
61796 * @private
61797 */
61798helpers_core.easingEffects = effects;
61799
61800var PI = Math.PI;
61801var RAD_PER_DEG = PI / 180;
61802var DOUBLE_PI = PI * 2;
61803var HALF_PI = PI / 2;
61804var QUARTER_PI = PI / 4;
61805var TWO_THIRDS_PI = PI * 2 / 3;
61806
61807/**
61808 * @namespace Chart.helpers.canvas
61809 */
61810var exports$1 = {
61811	/**
61812	 * Clears the entire canvas associated to the given `chart`.
61813	 * @param {Chart} chart - The chart for which to clear the canvas.
61814	 */
61815	clear: function(chart) {
61816		chart.ctx.clearRect(0, 0, chart.width, chart.height);
61817	},
61818
61819	/**
61820	 * Creates a "path" for a rectangle with rounded corners at position (x, y) with a
61821	 * given size (width, height) and the same `radius` for all corners.
61822	 * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context.
61823	 * @param {number} x - The x axis of the coordinate for the rectangle starting point.
61824	 * @param {number} y - The y axis of the coordinate for the rectangle starting point.
61825	 * @param {number} width - The rectangle's width.
61826	 * @param {number} height - The rectangle's height.
61827	 * @param {number} radius - The rounded amount (in pixels) for the four corners.
61828	 * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object?
61829	 */
61830	roundedRect: function(ctx, x, y, width, height, radius) {
61831		if (radius) {
61832			var r = Math.min(radius, height / 2, width / 2);
61833			var left = x + r;
61834			var top = y + r;
61835			var right = x + width - r;
61836			var bottom = y + height - r;
61837
61838			ctx.moveTo(x, top);
61839			if (left < right && top < bottom) {
61840				ctx.arc(left, top, r, -PI, -HALF_PI);
61841				ctx.arc(right, top, r, -HALF_PI, 0);
61842				ctx.arc(right, bottom, r, 0, HALF_PI);
61843				ctx.arc(left, bottom, r, HALF_PI, PI);
61844			} else if (left < right) {
61845				ctx.moveTo(left, y);
61846				ctx.arc(right, top, r, -HALF_PI, HALF_PI);
61847				ctx.arc(left, top, r, HALF_PI, PI + HALF_PI);
61848			} else if (top < bottom) {
61849				ctx.arc(left, top, r, -PI, 0);
61850				ctx.arc(left, bottom, r, 0, PI);
61851			} else {
61852				ctx.arc(left, top, r, -PI, PI);
61853			}
61854			ctx.closePath();
61855			ctx.moveTo(x, y);
61856		} else {
61857			ctx.rect(x, y, width, height);
61858		}
61859	},
61860
61861	drawPoint: function(ctx, style, radius, x, y, rotation) {
61862		var type, xOffset, yOffset, size, cornerRadius;
61863		var rad = (rotation || 0) * RAD_PER_DEG;
61864
61865		if (style && typeof style === 'object') {
61866			type = style.toString();
61867			if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
61868				ctx.drawImage(style, x - style.width / 2, y - style.height / 2, style.width, style.height);
61869				return;
61870			}
61871		}
61872
61873		if (isNaN(radius) || radius <= 0) {
61874			return;
61875		}
61876
61877		ctx.beginPath();
61878
61879		switch (style) {
61880		// Default includes circle
61881		default:
61882			ctx.arc(x, y, radius, 0, DOUBLE_PI);
61883			ctx.closePath();
61884			break;
61885		case 'triangle':
61886			ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
61887			rad += TWO_THIRDS_PI;
61888			ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
61889			rad += TWO_THIRDS_PI;
61890			ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
61891			ctx.closePath();
61892			break;
61893		case 'rectRounded':
61894			// NOTE: the rounded rect implementation changed to use `arc` instead of
61895			// `quadraticCurveTo` since it generates better results when rect is
61896			// almost a circle. 0.516 (instead of 0.5) produces results with visually
61897			// closer proportion to the previous impl and it is inscribed in the
61898			// circle with `radius`. For more details, see the following PRs:
61899			// https://github.com/chartjs/Chart.js/issues/5597
61900			// https://github.com/chartjs/Chart.js/issues/5858
61901			cornerRadius = radius * 0.516;
61902			size = radius - cornerRadius;
61903			xOffset = Math.cos(rad + QUARTER_PI) * size;
61904			yOffset = Math.sin(rad + QUARTER_PI) * size;
61905			ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);
61906			ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad);
61907			ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI);
61908			ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);
61909			ctx.closePath();
61910			break;
61911		case 'rect':
61912			if (!rotation) {
61913				size = Math.SQRT1_2 * radius;
61914				ctx.rect(x - size, y - size, 2 * size, 2 * size);
61915				break;
61916			}
61917			rad += QUARTER_PI;
61918			/* falls through */
61919		case 'rectRot':
61920			xOffset = Math.cos(rad) * radius;
61921			yOffset = Math.sin(rad) * radius;
61922			ctx.moveTo(x - xOffset, y - yOffset);
61923			ctx.lineTo(x + yOffset, y - xOffset);
61924			ctx.lineTo(x + xOffset, y + yOffset);
61925			ctx.lineTo(x - yOffset, y + xOffset);
61926			ctx.closePath();
61927			break;
61928		case 'crossRot':
61929			rad += QUARTER_PI;
61930			/* falls through */
61931		case 'cross':
61932			xOffset = Math.cos(rad) * radius;
61933			yOffset = Math.sin(rad) * radius;
61934			ctx.moveTo(x - xOffset, y - yOffset);
61935			ctx.lineTo(x + xOffset, y + yOffset);
61936			ctx.moveTo(x + yOffset, y - xOffset);
61937			ctx.lineTo(x - yOffset, y + xOffset);
61938			break;
61939		case 'star':
61940			xOffset = Math.cos(rad) * radius;
61941			yOffset = Math.sin(rad) * radius;
61942			ctx.moveTo(x - xOffset, y - yOffset);
61943			ctx.lineTo(x + xOffset, y + yOffset);
61944			ctx.moveTo(x + yOffset, y - xOffset);
61945			ctx.lineTo(x - yOffset, y + xOffset);
61946			rad += QUARTER_PI;
61947			xOffset = Math.cos(rad) * radius;
61948			yOffset = Math.sin(rad) * radius;
61949			ctx.moveTo(x - xOffset, y - yOffset);
61950			ctx.lineTo(x + xOffset, y + yOffset);
61951			ctx.moveTo(x + yOffset, y - xOffset);
61952			ctx.lineTo(x - yOffset, y + xOffset);
61953			break;
61954		case 'line':
61955			xOffset = Math.cos(rad) * radius;
61956			yOffset = Math.sin(rad) * radius;
61957			ctx.moveTo(x - xOffset, y - yOffset);
61958			ctx.lineTo(x + xOffset, y + yOffset);
61959			break;
61960		case 'dash':
61961			ctx.moveTo(x, y);
61962			ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius);
61963			break;
61964		}
61965
61966		ctx.fill();
61967		ctx.stroke();
61968	},
61969
61970	/**
61971	 * Returns true if the point is inside the rectangle
61972	 * @param {object} point - The point to test
61973	 * @param {object} area - The rectangle
61974	 * @returns {boolean}
61975	 * @private
61976	 */
61977	_isPointInArea: function(point, area) {
61978		var epsilon = 1e-6; // 1e-6 is margin in pixels for accumulated error.
61979
61980		return point.x > area.left - epsilon && point.x < area.right + epsilon &&
61981			point.y > area.top - epsilon && point.y < area.bottom + epsilon;
61982	},
61983
61984	clipArea: function(ctx, area) {
61985		ctx.save();
61986		ctx.beginPath();
61987		ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
61988		ctx.clip();
61989	},
61990
61991	unclipArea: function(ctx) {
61992		ctx.restore();
61993	},
61994
61995	lineTo: function(ctx, previous, target, flip) {
61996		var stepped = target.steppedLine;
61997		if (stepped) {
61998			if (stepped === 'middle') {
61999				var midpoint = (previous.x + target.x) / 2.0;
62000				ctx.lineTo(midpoint, flip ? target.y : previous.y);
62001				ctx.lineTo(midpoint, flip ? previous.y : target.y);
62002			} else if ((stepped === 'after' && !flip) || (stepped !== 'after' && flip)) {
62003				ctx.lineTo(previous.x, target.y);
62004			} else {
62005				ctx.lineTo(target.x, previous.y);
62006			}
62007			ctx.lineTo(target.x, target.y);
62008			return;
62009		}
62010
62011		if (!target.tension) {
62012			ctx.lineTo(target.x, target.y);
62013			return;
62014		}
62015
62016		ctx.bezierCurveTo(
62017			flip ? previous.controlPointPreviousX : previous.controlPointNextX,
62018			flip ? previous.controlPointPreviousY : previous.controlPointNextY,
62019			flip ? target.controlPointNextX : target.controlPointPreviousX,
62020			flip ? target.controlPointNextY : target.controlPointPreviousY,
62021			target.x,
62022			target.y);
62023	}
62024};
62025
62026var helpers_canvas = exports$1;
62027
62028// DEPRECATIONS
62029
62030/**
62031 * Provided for backward compatibility, use Chart.helpers.canvas.clear instead.
62032 * @namespace Chart.helpers.clear
62033 * @deprecated since version 2.7.0
62034 * @todo remove at version 3
62035 * @private
62036 */
62037helpers_core.clear = exports$1.clear;
62038
62039/**
62040 * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead.
62041 * @namespace Chart.helpers.drawRoundedRectangle
62042 * @deprecated since version 2.7.0
62043 * @todo remove at version 3
62044 * @private
62045 */
62046helpers_core.drawRoundedRectangle = function(ctx) {
62047	ctx.beginPath();
62048	exports$1.roundedRect.apply(exports$1, arguments);
62049};
62050
62051var defaults = {
62052	/**
62053	 * @private
62054	 */
62055	_set: function(scope, values) {
62056		return helpers_core.merge(this[scope] || (this[scope] = {}), values);
62057	}
62058};
62059
62060defaults._set('global', {
62061	defaultColor: 'rgba(0,0,0,0.1)',
62062	defaultFontColor: '#666',
62063	defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
62064	defaultFontSize: 12,
62065	defaultFontStyle: 'normal',
62066	defaultLineHeight: 1.2,
62067	showLines: true
62068});
62069
62070var core_defaults = defaults;
62071
62072var valueOrDefault = helpers_core.valueOrDefault;
62073
62074/**
62075 * Converts the given font object into a CSS font string.
62076 * @param {object} font - A font object.
62077 * @return {string} The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font
62078 * @private
62079 */
62080function toFontString(font) {
62081	if (!font || helpers_core.isNullOrUndef(font.size) || helpers_core.isNullOrUndef(font.family)) {
62082		return null;
62083	}
62084
62085	return (font.style ? font.style + ' ' : '')
62086		+ (font.weight ? font.weight + ' ' : '')
62087		+ font.size + 'px '
62088		+ font.family;
62089}
62090
62091/**
62092 * @alias Chart.helpers.options
62093 * @namespace
62094 */
62095var helpers_options = {
62096	/**
62097	 * Converts the given line height `value` in pixels for a specific font `size`.
62098	 * @param {number|string} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
62099	 * @param {number} size - The font size (in pixels) used to resolve relative `value`.
62100	 * @returns {number} The effective line height in pixels (size * 1.2 if value is invalid).
62101	 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
62102	 * @since 2.7.0
62103	 */
62104	toLineHeight: function(value, size) {
62105		var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
62106		if (!matches || matches[1] === 'normal') {
62107			return size * 1.2;
62108		}
62109
62110		value = +matches[2];
62111
62112		switch (matches[3]) {
62113		case 'px':
62114			return value;
62115		case '%':
62116			value /= 100;
62117			break;
62118		default:
62119			break;
62120		}
62121
62122		return size * value;
62123	},
62124
62125	/**
62126	 * Converts the given value into a padding object with pre-computed width/height.
62127	 * @param {number|object} value - If a number, set the value to all TRBL component,
62128	 *  else, if and object, use defined properties and sets undefined ones to 0.
62129	 * @returns {object} The padding values (top, right, bottom, left, width, height)
62130	 * @since 2.7.0
62131	 */
62132	toPadding: function(value) {
62133		var t, r, b, l;
62134
62135		if (helpers_core.isObject(value)) {
62136			t = +value.top || 0;
62137			r = +value.right || 0;
62138			b = +value.bottom || 0;
62139			l = +value.left || 0;
62140		} else {
62141			t = r = b = l = +value || 0;
62142		}
62143
62144		return {
62145			top: t,
62146			right: r,
62147			bottom: b,
62148			left: l,
62149			height: t + b,
62150			width: l + r
62151		};
62152	},
62153
62154	/**
62155	 * Parses font options and returns the font object.
62156	 * @param {object} options - A object that contains font options to be parsed.
62157	 * @return {object} The font object.
62158	 * @todo Support font.* options and renamed to toFont().
62159	 * @private
62160	 */
62161	_parseFont: function(options) {
62162		var globalDefaults = core_defaults.global;
62163		var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize);
62164		var font = {
62165			family: valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily),
62166			lineHeight: helpers_core.options.toLineHeight(valueOrDefault(options.lineHeight, globalDefaults.defaultLineHeight), size),
62167			size: size,
62168			style: valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle),
62169			weight: null,
62170			string: ''
62171		};
62172
62173		font.string = toFontString(font);
62174		return font;
62175	},
62176
62177	/**
62178	 * Evaluates the given `inputs` sequentially and returns the first defined value.
62179	 * @param {Array} inputs - An array of values, falling back to the last value.
62180	 * @param {object} [context] - If defined and the current value is a function, the value
62181	 * is called with `context` as first argument and the result becomes the new input.
62182	 * @param {number} [index] - If defined and the current value is an array, the value
62183	 * at `index` become the new input.
62184	 * @since 2.7.0
62185	 */
62186	resolve: function(inputs, context, index) {
62187		var i, ilen, value;
62188
62189		for (i = 0, ilen = inputs.length; i < ilen; ++i) {
62190			value = inputs[i];
62191			if (value === undefined) {
62192				continue;
62193			}
62194			if (context !== undefined && typeof value === 'function') {
62195				value = value(context);
62196			}
62197			if (index !== undefined && helpers_core.isArray(value)) {
62198				value = value[index];
62199			}
62200			if (value !== undefined) {
62201				return value;
62202			}
62203		}
62204	}
62205};
62206
62207var helpers$1 = helpers_core;
62208var easing = helpers_easing;
62209var canvas = helpers_canvas;
62210var options = helpers_options;
62211helpers$1.easing = easing;
62212helpers$1.canvas = canvas;
62213helpers$1.options = options;
62214
62215function interpolate(start, view, model, ease) {
62216	var keys = Object.keys(model);
62217	var i, ilen, key, actual, origin, target, type, c0, c1;
62218
62219	for (i = 0, ilen = keys.length; i < ilen; ++i) {
62220		key = keys[i];
62221
62222		target = model[key];
62223
62224		// if a value is added to the model after pivot() has been called, the view
62225		// doesn't contain it, so let's initialize the view to the target value.
62226		if (!view.hasOwnProperty(key)) {
62227			view[key] = target;
62228		}
62229
62230		actual = view[key];
62231
62232		if (actual === target || key[0] === '_') {
62233			continue;
62234		}
62235
62236		if (!start.hasOwnProperty(key)) {
62237			start[key] = actual;
62238		}
62239
62240		origin = start[key];
62241
62242		type = typeof target;
62243
62244		if (type === typeof origin) {
62245			if (type === 'string') {
62246				c0 = chartjsColor(origin);
62247				if (c0.valid) {
62248					c1 = chartjsColor(target);
62249					if (c1.valid) {
62250						view[key] = c1.mix(c0, ease).rgbString();
62251						continue;
62252					}
62253				}
62254			} else if (helpers$1.isFinite(origin) && helpers$1.isFinite(target)) {
62255				view[key] = origin + (target - origin) * ease;
62256				continue;
62257			}
62258		}
62259
62260		view[key] = target;
62261	}
62262}
62263
62264var Element = function(configuration) {
62265	helpers$1.extend(this, configuration);
62266	this.initialize.apply(this, arguments);
62267};
62268
62269helpers$1.extend(Element.prototype, {
62270
62271	initialize: function() {
62272		this.hidden = false;
62273	},
62274
62275	pivot: function() {
62276		var me = this;
62277		if (!me._view) {
62278			me._view = helpers$1.clone(me._model);
62279		}
62280		me._start = {};
62281		return me;
62282	},
62283
62284	transition: function(ease) {
62285		var me = this;
62286		var model = me._model;
62287		var start = me._start;
62288		var view = me._view;
62289
62290		// No animation -> No Transition
62291		if (!model || ease === 1) {
62292			me._view = model;
62293			me._start = null;
62294			return me;
62295		}
62296
62297		if (!view) {
62298			view = me._view = {};
62299		}
62300
62301		if (!start) {
62302			start = me._start = {};
62303		}
62304
62305		interpolate(start, view, model, ease);
62306
62307		return me;
62308	},
62309
62310	tooltipPosition: function() {
62311		return {
62312			x: this._model.x,
62313			y: this._model.y
62314		};
62315	},
62316
62317	hasValue: function() {
62318		return helpers$1.isNumber(this._model.x) && helpers$1.isNumber(this._model.y);
62319	}
62320});
62321
62322Element.extend = helpers$1.inherits;
62323
62324var core_element = Element;
62325
62326var exports$2 = core_element.extend({
62327	chart: null, // the animation associated chart instance
62328	currentStep: 0, // the current animation step
62329	numSteps: 60, // default number of steps
62330	easing: '', // the easing to use for this animation
62331	render: null, // render function used by the animation service
62332
62333	onAnimationProgress: null, // user specified callback to fire on each step of the animation
62334	onAnimationComplete: null, // user specified callback to fire when the animation finishes
62335});
62336
62337var core_animation = exports$2;
62338
62339// DEPRECATIONS
62340
62341/**
62342 * Provided for backward compatibility, use Chart.Animation instead
62343 * @prop Chart.Animation#animationObject
62344 * @deprecated since version 2.6.0
62345 * @todo remove at version 3
62346 */
62347Object.defineProperty(exports$2.prototype, 'animationObject', {
62348	get: function() {
62349		return this;
62350	}
62351});
62352
62353/**
62354 * Provided for backward compatibility, use Chart.Animation#chart instead
62355 * @prop Chart.Animation#chartInstance
62356 * @deprecated since version 2.6.0
62357 * @todo remove at version 3
62358 */
62359Object.defineProperty(exports$2.prototype, 'chartInstance', {
62360	get: function() {
62361		return this.chart;
62362	},
62363	set: function(value) {
62364		this.chart = value;
62365	}
62366});
62367
62368core_defaults._set('global', {
62369	animation: {
62370		duration: 1000,
62371		easing: 'easeOutQuart',
62372		onProgress: helpers$1.noop,
62373		onComplete: helpers$1.noop
62374	}
62375});
62376
62377var core_animations = {
62378	animations: [],
62379	request: null,
62380
62381	/**
62382	 * @param {Chart} chart - The chart to animate.
62383	 * @param {Chart.Animation} animation - The animation that we will animate.
62384	 * @param {number} duration - The animation duration in ms.
62385	 * @param {boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions
62386	 */
62387	addAnimation: function(chart, animation, duration, lazy) {
62388		var animations = this.animations;
62389		var i, ilen;
62390
62391		animation.chart = chart;
62392		animation.startTime = Date.now();
62393		animation.duration = duration;
62394
62395		if (!lazy) {
62396			chart.animating = true;
62397		}
62398
62399		for (i = 0, ilen = animations.length; i < ilen; ++i) {
62400			if (animations[i].chart === chart) {
62401				animations[i] = animation;
62402				return;
62403			}
62404		}
62405
62406		animations.push(animation);
62407
62408		// If there are no animations queued, manually kickstart a digest, for lack of a better word
62409		if (animations.length === 1) {
62410			this.requestAnimationFrame();
62411		}
62412	},
62413
62414	cancelAnimation: function(chart) {
62415		var index = helpers$1.findIndex(this.animations, function(animation) {
62416			return animation.chart === chart;
62417		});
62418
62419		if (index !== -1) {
62420			this.animations.splice(index, 1);
62421			chart.animating = false;
62422		}
62423	},
62424
62425	requestAnimationFrame: function() {
62426		var me = this;
62427		if (me.request === null) {
62428			// Skip animation frame requests until the active one is executed.
62429			// This can happen when processing mouse events, e.g. 'mousemove'
62430			// and 'mouseout' events will trigger multiple renders.
62431			me.request = helpers$1.requestAnimFrame.call(window, function() {
62432				me.request = null;
62433				me.startDigest();
62434			});
62435		}
62436	},
62437
62438	/**
62439	 * @private
62440	 */
62441	startDigest: function() {
62442		var me = this;
62443
62444		me.advance();
62445
62446		// Do we have more stuff to animate?
62447		if (me.animations.length > 0) {
62448			me.requestAnimationFrame();
62449		}
62450	},
62451
62452	/**
62453	 * @private
62454	 */
62455	advance: function() {
62456		var animations = this.animations;
62457		var animation, chart, numSteps, nextStep;
62458		var i = 0;
62459
62460		// 1 animation per chart, so we are looping charts here
62461		while (i < animations.length) {
62462			animation = animations[i];
62463			chart = animation.chart;
62464			numSteps = animation.numSteps;
62465
62466			// Make sure that currentStep starts at 1
62467			// https://github.com/chartjs/Chart.js/issues/6104
62468			nextStep = Math.floor((Date.now() - animation.startTime) / animation.duration * numSteps) + 1;
62469			animation.currentStep = Math.min(nextStep, numSteps);
62470
62471			helpers$1.callback(animation.render, [chart, animation], chart);
62472			helpers$1.callback(animation.onAnimationProgress, [animation], chart);
62473
62474			if (animation.currentStep >= numSteps) {
62475				helpers$1.callback(animation.onAnimationComplete, [animation], chart);
62476				chart.animating = false;
62477				animations.splice(i, 1);
62478			} else {
62479				++i;
62480			}
62481		}
62482	}
62483};
62484
62485var resolve = helpers$1.options.resolve;
62486
62487var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];
62488
62489/**
62490 * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice',
62491 * 'unshift') and notify the listener AFTER the array has been altered. Listeners are
62492 * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments.
62493 */
62494function listenArrayEvents(array, listener) {
62495	if (array._chartjs) {
62496		array._chartjs.listeners.push(listener);
62497		return;
62498	}
62499
62500	Object.defineProperty(array, '_chartjs', {
62501		configurable: true,
62502		enumerable: false,
62503		value: {
62504			listeners: [listener]
62505		}
62506	});
62507
62508	arrayEvents.forEach(function(key) {
62509		var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1);
62510		var base = array[key];
62511
62512		Object.defineProperty(array, key, {
62513			configurable: true,
62514			enumerable: false,
62515			value: function() {
62516				var args = Array.prototype.slice.call(arguments);
62517				var res = base.apply(this, args);
62518
62519				helpers$1.each(array._chartjs.listeners, function(object) {
62520					if (typeof object[method] === 'function') {
62521						object[method].apply(object, args);
62522					}
62523				});
62524
62525				return res;
62526			}
62527		});
62528	});
62529}
62530
62531/**
62532 * Removes the given array event listener and cleanup extra attached properties (such as
62533 * the _chartjs stub and overridden methods) if array doesn't have any more listeners.
62534 */
62535function unlistenArrayEvents(array, listener) {
62536	var stub = array._chartjs;
62537	if (!stub) {
62538		return;
62539	}
62540
62541	var listeners = stub.listeners;
62542	var index = listeners.indexOf(listener);
62543	if (index !== -1) {
62544		listeners.splice(index, 1);
62545	}
62546
62547	if (listeners.length > 0) {
62548		return;
62549	}
62550
62551	arrayEvents.forEach(function(key) {
62552		delete array[key];
62553	});
62554
62555	delete array._chartjs;
62556}
62557
62558// Base class for all dataset controllers (line, bar, etc)
62559var DatasetController = function(chart, datasetIndex) {
62560	this.initialize(chart, datasetIndex);
62561};
62562
62563helpers$1.extend(DatasetController.prototype, {
62564
62565	/**
62566	 * Element type used to generate a meta dataset (e.g. Chart.element.Line).
62567	 * @type {Chart.core.element}
62568	 */
62569	datasetElementType: null,
62570
62571	/**
62572	 * Element type used to generate a meta data (e.g. Chart.element.Point).
62573	 * @type {Chart.core.element}
62574	 */
62575	dataElementType: null,
62576
62577	initialize: function(chart, datasetIndex) {
62578		var me = this;
62579		me.chart = chart;
62580		me.index = datasetIndex;
62581		me.linkScales();
62582		me.addElements();
62583	},
62584
62585	updateIndex: function(datasetIndex) {
62586		this.index = datasetIndex;
62587	},
62588
62589	linkScales: function() {
62590		var me = this;
62591		var meta = me.getMeta();
62592		var dataset = me.getDataset();
62593
62594		if (meta.xAxisID === null || !(meta.xAxisID in me.chart.scales)) {
62595			meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id;
62596		}
62597		if (meta.yAxisID === null || !(meta.yAxisID in me.chart.scales)) {
62598			meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id;
62599		}
62600	},
62601
62602	getDataset: function() {
62603		return this.chart.data.datasets[this.index];
62604	},
62605
62606	getMeta: function() {
62607		return this.chart.getDatasetMeta(this.index);
62608	},
62609
62610	getScaleForId: function(scaleID) {
62611		return this.chart.scales[scaleID];
62612	},
62613
62614	/**
62615	 * @private
62616	 */
62617	_getValueScaleId: function() {
62618		return this.getMeta().yAxisID;
62619	},
62620
62621	/**
62622	 * @private
62623	 */
62624	_getIndexScaleId: function() {
62625		return this.getMeta().xAxisID;
62626	},
62627
62628	/**
62629	 * @private
62630	 */
62631	_getValueScale: function() {
62632		return this.getScaleForId(this._getValueScaleId());
62633	},
62634
62635	/**
62636	 * @private
62637	 */
62638	_getIndexScale: function() {
62639		return this.getScaleForId(this._getIndexScaleId());
62640	},
62641
62642	reset: function() {
62643		this.update(true);
62644	},
62645
62646	/**
62647	 * @private
62648	 */
62649	destroy: function() {
62650		if (this._data) {
62651			unlistenArrayEvents(this._data, this);
62652		}
62653	},
62654
62655	createMetaDataset: function() {
62656		var me = this;
62657		var type = me.datasetElementType;
62658		return type && new type({
62659			_chart: me.chart,
62660			_datasetIndex: me.index
62661		});
62662	},
62663
62664	createMetaData: function(index) {
62665		var me = this;
62666		var type = me.dataElementType;
62667		return type && new type({
62668			_chart: me.chart,
62669			_datasetIndex: me.index,
62670			_index: index
62671		});
62672	},
62673
62674	addElements: function() {
62675		var me = this;
62676		var meta = me.getMeta();
62677		var data = me.getDataset().data || [];
62678		var metaData = meta.data;
62679		var i, ilen;
62680
62681		for (i = 0, ilen = data.length; i < ilen; ++i) {
62682			metaData[i] = metaData[i] || me.createMetaData(i);
62683		}
62684
62685		meta.dataset = meta.dataset || me.createMetaDataset();
62686	},
62687
62688	addElementAndReset: function(index) {
62689		var element = this.createMetaData(index);
62690		this.getMeta().data.splice(index, 0, element);
62691		this.updateElement(element, index, true);
62692	},
62693
62694	buildOrUpdateElements: function() {
62695		var me = this;
62696		var dataset = me.getDataset();
62697		var data = dataset.data || (dataset.data = []);
62698
62699		// In order to correctly handle data addition/deletion animation (an thus simulate
62700		// real-time charts), we need to monitor these data modifications and synchronize
62701		// the internal meta data accordingly.
62702		if (me._data !== data) {
62703			if (me._data) {
62704				// This case happens when the user replaced the data array instance.
62705				unlistenArrayEvents(me._data, me);
62706			}
62707
62708			if (data && Object.isExtensible(data)) {
62709				listenArrayEvents(data, me);
62710			}
62711			me._data = data;
62712		}
62713
62714		// Re-sync meta data in case the user replaced the data array or if we missed
62715		// any updates and so make sure that we handle number of datapoints changing.
62716		me.resyncElements();
62717	},
62718
62719	update: helpers$1.noop,
62720
62721	transition: function(easingValue) {
62722		var meta = this.getMeta();
62723		var elements = meta.data || [];
62724		var ilen = elements.length;
62725		var i = 0;
62726
62727		for (; i < ilen; ++i) {
62728			elements[i].transition(easingValue);
62729		}
62730
62731		if (meta.dataset) {
62732			meta.dataset.transition(easingValue);
62733		}
62734	},
62735
62736	draw: function() {
62737		var meta = this.getMeta();
62738		var elements = meta.data || [];
62739		var ilen = elements.length;
62740		var i = 0;
62741
62742		if (meta.dataset) {
62743			meta.dataset.draw();
62744		}
62745
62746		for (; i < ilen; ++i) {
62747			elements[i].draw();
62748		}
62749	},
62750
62751	removeHoverStyle: function(element) {
62752		helpers$1.merge(element._model, element.$previousStyle || {});
62753		delete element.$previousStyle;
62754	},
62755
62756	setHoverStyle: function(element) {
62757		var dataset = this.chart.data.datasets[element._datasetIndex];
62758		var index = element._index;
62759		var custom = element.custom || {};
62760		var model = element._model;
62761		var getHoverColor = helpers$1.getHoverColor;
62762
62763		element.$previousStyle = {
62764			backgroundColor: model.backgroundColor,
62765			borderColor: model.borderColor,
62766			borderWidth: model.borderWidth
62767		};
62768
62769		model.backgroundColor = resolve([custom.hoverBackgroundColor, dataset.hoverBackgroundColor, getHoverColor(model.backgroundColor)], undefined, index);
62770		model.borderColor = resolve([custom.hoverBorderColor, dataset.hoverBorderColor, getHoverColor(model.borderColor)], undefined, index);
62771		model.borderWidth = resolve([custom.hoverBorderWidth, dataset.hoverBorderWidth, model.borderWidth], undefined, index);
62772	},
62773
62774	/**
62775	 * @private
62776	 */
62777	resyncElements: function() {
62778		var me = this;
62779		var meta = me.getMeta();
62780		var data = me.getDataset().data;
62781		var numMeta = meta.data.length;
62782		var numData = data.length;
62783
62784		if (numData < numMeta) {
62785			meta.data.splice(numData, numMeta - numData);
62786		} else if (numData > numMeta) {
62787			me.insertElements(numMeta, numData - numMeta);
62788		}
62789	},
62790
62791	/**
62792	 * @private
62793	 */
62794	insertElements: function(start, count) {
62795		for (var i = 0; i < count; ++i) {
62796			this.addElementAndReset(start + i);
62797		}
62798	},
62799
62800	/**
62801	 * @private
62802	 */
62803	onDataPush: function() {
62804		var count = arguments.length;
62805		this.insertElements(this.getDataset().data.length - count, count);
62806	},
62807
62808	/**
62809	 * @private
62810	 */
62811	onDataPop: function() {
62812		this.getMeta().data.pop();
62813	},
62814
62815	/**
62816	 * @private
62817	 */
62818	onDataShift: function() {
62819		this.getMeta().data.shift();
62820	},
62821
62822	/**
62823	 * @private
62824	 */
62825	onDataSplice: function(start, count) {
62826		this.getMeta().data.splice(start, count);
62827		this.insertElements(start, arguments.length - 2);
62828	},
62829
62830	/**
62831	 * @private
62832	 */
62833	onDataUnshift: function() {
62834		this.insertElements(0, arguments.length);
62835	}
62836});
62837
62838DatasetController.extend = helpers$1.inherits;
62839
62840var core_datasetController = DatasetController;
62841
62842core_defaults._set('global', {
62843	elements: {
62844		arc: {
62845			backgroundColor: core_defaults.global.defaultColor,
62846			borderColor: '#fff',
62847			borderWidth: 2,
62848			borderAlign: 'center'
62849		}
62850	}
62851});
62852
62853var element_arc = core_element.extend({
62854	inLabelRange: function(mouseX) {
62855		var vm = this._view;
62856
62857		if (vm) {
62858			return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));
62859		}
62860		return false;
62861	},
62862
62863	inRange: function(chartX, chartY) {
62864		var vm = this._view;
62865
62866		if (vm) {
62867			var pointRelativePosition = helpers$1.getAngleFromPoint(vm, {x: chartX, y: chartY});
62868			var	angle = pointRelativePosition.angle;
62869			var distance = pointRelativePosition.distance;
62870
62871			// Sanitise angle range
62872			var startAngle = vm.startAngle;
62873			var endAngle = vm.endAngle;
62874			while (endAngle < startAngle) {
62875				endAngle += 2.0 * Math.PI;
62876			}
62877			while (angle > endAngle) {
62878				angle -= 2.0 * Math.PI;
62879			}
62880			while (angle < startAngle) {
62881				angle += 2.0 * Math.PI;
62882			}
62883
62884			// Check if within the range of the open/close angle
62885			var betweenAngles = (angle >= startAngle && angle <= endAngle);
62886			var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
62887
62888			return (betweenAngles && withinRadius);
62889		}
62890		return false;
62891	},
62892
62893	getCenterPoint: function() {
62894		var vm = this._view;
62895		var halfAngle = (vm.startAngle + vm.endAngle) / 2;
62896		var halfRadius = (vm.innerRadius + vm.outerRadius) / 2;
62897		return {
62898			x: vm.x + Math.cos(halfAngle) * halfRadius,
62899			y: vm.y + Math.sin(halfAngle) * halfRadius
62900		};
62901	},
62902
62903	getArea: function() {
62904		var vm = this._view;
62905		return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2));
62906	},
62907
62908	tooltipPosition: function() {
62909		var vm = this._view;
62910		var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2);
62911		var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
62912
62913		return {
62914			x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
62915			y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
62916		};
62917	},
62918
62919	draw: function() {
62920		var ctx = this._chart.ctx;
62921		var vm = this._view;
62922		var sA = vm.startAngle;
62923		var eA = vm.endAngle;
62924		var pixelMargin = (vm.borderAlign === 'inner') ? 0.33 : 0;
62925		var angleMargin;
62926
62927		ctx.save();
62928
62929		ctx.beginPath();
62930		ctx.arc(vm.x, vm.y, Math.max(vm.outerRadius - pixelMargin, 0), sA, eA);
62931		ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
62932		ctx.closePath();
62933
62934		ctx.fillStyle = vm.backgroundColor;
62935		ctx.fill();
62936
62937		if (vm.borderWidth) {
62938			if (vm.borderAlign === 'inner') {
62939				// Draw an inner border by cliping the arc and drawing a double-width border
62940				// Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders
62941				ctx.beginPath();
62942				angleMargin = pixelMargin / vm.outerRadius;
62943				ctx.arc(vm.x, vm.y, vm.outerRadius, sA - angleMargin, eA + angleMargin);
62944				if (vm.innerRadius > pixelMargin) {
62945					angleMargin = pixelMargin / vm.innerRadius;
62946					ctx.arc(vm.x, vm.y, vm.innerRadius - pixelMargin, eA + angleMargin, sA - angleMargin, true);
62947				} else {
62948					ctx.arc(vm.x, vm.y, pixelMargin, eA + Math.PI / 2, sA - Math.PI / 2);
62949				}
62950				ctx.closePath();
62951				ctx.clip();
62952
62953				ctx.beginPath();
62954				ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);
62955				ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
62956				ctx.closePath();
62957
62958				ctx.lineWidth = vm.borderWidth * 2;
62959				ctx.lineJoin = 'round';
62960			} else {
62961				ctx.lineWidth = vm.borderWidth;
62962				ctx.lineJoin = 'bevel';
62963			}
62964
62965			ctx.strokeStyle = vm.borderColor;
62966			ctx.stroke();
62967		}
62968
62969		ctx.restore();
62970	}
62971});
62972
62973var valueOrDefault$1 = helpers$1.valueOrDefault;
62974
62975var defaultColor = core_defaults.global.defaultColor;
62976
62977core_defaults._set('global', {
62978	elements: {
62979		line: {
62980			tension: 0.4,
62981			backgroundColor: defaultColor,
62982			borderWidth: 3,
62983			borderColor: defaultColor,
62984			borderCapStyle: 'butt',
62985			borderDash: [],
62986			borderDashOffset: 0.0,
62987			borderJoinStyle: 'miter',
62988			capBezierPoints: true,
62989			fill: true, // do we fill in the area between the line and its base axis
62990		}
62991	}
62992});
62993
62994var element_line = core_element.extend({
62995	draw: function() {
62996		var me = this;
62997		var vm = me._view;
62998		var ctx = me._chart.ctx;
62999		var spanGaps = vm.spanGaps;
63000		var points = me._children.slice(); // clone array
63001		var globalDefaults = core_defaults.global;
63002		var globalOptionLineElements = globalDefaults.elements.line;
63003		var lastDrawnIndex = -1;
63004		var index, current, previous, currentVM;
63005
63006		// If we are looping, adding the first point again
63007		if (me._loop && points.length) {
63008			points.push(points[0]);
63009		}
63010
63011		ctx.save();
63012
63013		// Stroke Line Options
63014		ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
63015
63016		// IE 9 and 10 do not support line dash
63017		if (ctx.setLineDash) {
63018			ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
63019		}
63020
63021		ctx.lineDashOffset = valueOrDefault$1(vm.borderDashOffset, globalOptionLineElements.borderDashOffset);
63022		ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
63023		ctx.lineWidth = valueOrDefault$1(vm.borderWidth, globalOptionLineElements.borderWidth);
63024		ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
63025
63026		// Stroke Line
63027		ctx.beginPath();
63028		lastDrawnIndex = -1;
63029
63030		for (index = 0; index < points.length; ++index) {
63031			current = points[index];
63032			previous = helpers$1.previousItem(points, index);
63033			currentVM = current._view;
63034
63035			// First point moves to it's starting position no matter what
63036			if (index === 0) {
63037				if (!currentVM.skip) {
63038					ctx.moveTo(currentVM.x, currentVM.y);
63039					lastDrawnIndex = index;
63040				}
63041			} else {
63042				previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
63043
63044				if (!currentVM.skip) {
63045					if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
63046						// There was a gap and this is the first point after the gap
63047						ctx.moveTo(currentVM.x, currentVM.y);
63048					} else {
63049						// Line to next point
63050						helpers$1.canvas.lineTo(ctx, previous._view, current._view);
63051					}
63052					lastDrawnIndex = index;
63053				}
63054			}
63055		}
63056
63057		ctx.stroke();
63058		ctx.restore();
63059	}
63060});
63061
63062var valueOrDefault$2 = helpers$1.valueOrDefault;
63063
63064var defaultColor$1 = core_defaults.global.defaultColor;
63065
63066core_defaults._set('global', {
63067	elements: {
63068		point: {
63069			radius: 3,
63070			pointStyle: 'circle',
63071			backgroundColor: defaultColor$1,
63072			borderColor: defaultColor$1,
63073			borderWidth: 1,
63074			// Hover
63075			hitRadius: 1,
63076			hoverRadius: 4,
63077			hoverBorderWidth: 1
63078		}
63079	}
63080});
63081
63082function xRange(mouseX) {
63083	var vm = this._view;
63084	return vm ? (Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius) : false;
63085}
63086
63087function yRange(mouseY) {
63088	var vm = this._view;
63089	return vm ? (Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius) : false;
63090}
63091
63092var element_point = core_element.extend({
63093	inRange: function(mouseX, mouseY) {
63094		var vm = this._view;
63095		return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
63096	},
63097
63098	inLabelRange: xRange,
63099	inXRange: xRange,
63100	inYRange: yRange,
63101
63102	getCenterPoint: function() {
63103		var vm = this._view;
63104		return {
63105			x: vm.x,
63106			y: vm.y
63107		};
63108	},
63109
63110	getArea: function() {
63111		return Math.PI * Math.pow(this._view.radius, 2);
63112	},
63113
63114	tooltipPosition: function() {
63115		var vm = this._view;
63116		return {
63117			x: vm.x,
63118			y: vm.y,
63119			padding: vm.radius + vm.borderWidth
63120		};
63121	},
63122
63123	draw: function(chartArea) {
63124		var vm = this._view;
63125		var ctx = this._chart.ctx;
63126		var pointStyle = vm.pointStyle;
63127		var rotation = vm.rotation;
63128		var radius = vm.radius;
63129		var x = vm.x;
63130		var y = vm.y;
63131		var globalDefaults = core_defaults.global;
63132		var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow
63133
63134		if (vm.skip) {
63135			return;
63136		}
63137
63138		// Clipping for Points.
63139		if (chartArea === undefined || helpers$1.canvas._isPointInArea(vm, chartArea)) {
63140			ctx.strokeStyle = vm.borderColor || defaultColor;
63141			ctx.lineWidth = valueOrDefault$2(vm.borderWidth, globalDefaults.elements.point.borderWidth);
63142			ctx.fillStyle = vm.backgroundColor || defaultColor;
63143			helpers$1.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation);
63144		}
63145	}
63146});
63147
63148var defaultColor$2 = core_defaults.global.defaultColor;
63149
63150core_defaults._set('global', {
63151	elements: {
63152		rectangle: {
63153			backgroundColor: defaultColor$2,
63154			borderColor: defaultColor$2,
63155			borderSkipped: 'bottom',
63156			borderWidth: 0
63157		}
63158	}
63159});
63160
63161function isVertical(vm) {
63162	return vm && vm.width !== undefined;
63163}
63164
63165/**
63166 * Helper function to get the bounds of the bar regardless of the orientation
63167 * @param bar {Chart.Element.Rectangle} the bar
63168 * @return {Bounds} bounds of the bar
63169 * @private
63170 */
63171function getBarBounds(vm) {
63172	var x1, x2, y1, y2, half;
63173
63174	if (isVertical(vm)) {
63175		half = vm.width / 2;
63176		x1 = vm.x - half;
63177		x2 = vm.x + half;
63178		y1 = Math.min(vm.y, vm.base);
63179		y2 = Math.max(vm.y, vm.base);
63180	} else {
63181		half = vm.height / 2;
63182		x1 = Math.min(vm.x, vm.base);
63183		x2 = Math.max(vm.x, vm.base);
63184		y1 = vm.y - half;
63185		y2 = vm.y + half;
63186	}
63187
63188	return {
63189		left: x1,
63190		top: y1,
63191		right: x2,
63192		bottom: y2
63193	};
63194}
63195
63196function swap(orig, v1, v2) {
63197	return orig === v1 ? v2 : orig === v2 ? v1 : orig;
63198}
63199
63200function parseBorderSkipped(vm) {
63201	var edge = vm.borderSkipped;
63202	var res = {};
63203
63204	if (!edge) {
63205		return res;
63206	}
63207
63208	if (vm.horizontal) {
63209		if (vm.base > vm.x) {
63210			edge = swap(edge, 'left', 'right');
63211		}
63212	} else if (vm.base < vm.y) {
63213		edge = swap(edge, 'bottom', 'top');
63214	}
63215
63216	res[edge] = true;
63217	return res;
63218}
63219
63220function parseBorderWidth(vm, maxW, maxH) {
63221	var value = vm.borderWidth;
63222	var skip = parseBorderSkipped(vm);
63223	var t, r, b, l;
63224
63225	if (helpers$1.isObject(value)) {
63226		t = +value.top || 0;
63227		r = +value.right || 0;
63228		b = +value.bottom || 0;
63229		l = +value.left || 0;
63230	} else {
63231		t = r = b = l = +value || 0;
63232	}
63233
63234	return {
63235		t: skip.top || (t < 0) ? 0 : t > maxH ? maxH : t,
63236		r: skip.right || (r < 0) ? 0 : r > maxW ? maxW : r,
63237		b: skip.bottom || (b < 0) ? 0 : b > maxH ? maxH : b,
63238		l: skip.left || (l < 0) ? 0 : l > maxW ? maxW : l
63239	};
63240}
63241
63242function boundingRects(vm) {
63243	var bounds = getBarBounds(vm);
63244	var width = bounds.right - bounds.left;
63245	var height = bounds.bottom - bounds.top;
63246	var border = parseBorderWidth(vm, width / 2, height / 2);
63247
63248	return {
63249		outer: {
63250			x: bounds.left,
63251			y: bounds.top,
63252			w: width,
63253			h: height
63254		},
63255		inner: {
63256			x: bounds.left + border.l,
63257			y: bounds.top + border.t,
63258			w: width - border.l - border.r,
63259			h: height - border.t - border.b
63260		}
63261	};
63262}
63263
63264function inRange(vm, x, y) {
63265	var skipX = x === null;
63266	var skipY = y === null;
63267	var bounds = !vm || (skipX && skipY) ? false : getBarBounds(vm);
63268
63269	return bounds
63270		&& (skipX || x >= bounds.left && x <= bounds.right)
63271		&& (skipY || y >= bounds.top && y <= bounds.bottom);
63272}
63273
63274var element_rectangle = core_element.extend({
63275	draw: function() {
63276		var ctx = this._chart.ctx;
63277		var vm = this._view;
63278		var rects = boundingRects(vm);
63279		var outer = rects.outer;
63280		var inner = rects.inner;
63281
63282		ctx.fillStyle = vm.backgroundColor;
63283		ctx.fillRect(outer.x, outer.y, outer.w, outer.h);
63284
63285		if (outer.w === inner.w && outer.h === inner.h) {
63286			return;
63287		}
63288
63289		ctx.save();
63290		ctx.beginPath();
63291		ctx.rect(outer.x, outer.y, outer.w, outer.h);
63292		ctx.clip();
63293		ctx.fillStyle = vm.borderColor;
63294		ctx.rect(inner.x, inner.y, inner.w, inner.h);
63295		ctx.fill('evenodd');
63296		ctx.restore();
63297	},
63298
63299	height: function() {
63300		var vm = this._view;
63301		return vm.base - vm.y;
63302	},
63303
63304	inRange: function(mouseX, mouseY) {
63305		return inRange(this._view, mouseX, mouseY);
63306	},
63307
63308	inLabelRange: function(mouseX, mouseY) {
63309		var vm = this._view;
63310		return isVertical(vm)
63311			? inRange(vm, mouseX, null)
63312			: inRange(vm, null, mouseY);
63313	},
63314
63315	inXRange: function(mouseX) {
63316		return inRange(this._view, mouseX, null);
63317	},
63318
63319	inYRange: function(mouseY) {
63320		return inRange(this._view, null, mouseY);
63321	},
63322
63323	getCenterPoint: function() {
63324		var vm = this._view;
63325		var x, y;
63326		if (isVertical(vm)) {
63327			x = vm.x;
63328			y = (vm.y + vm.base) / 2;
63329		} else {
63330			x = (vm.x + vm.base) / 2;
63331			y = vm.y;
63332		}
63333
63334		return {x: x, y: y};
63335	},
63336
63337	getArea: function() {
63338		var vm = this._view;
63339
63340		return isVertical(vm)
63341			? vm.width * Math.abs(vm.y - vm.base)
63342			: vm.height * Math.abs(vm.x - vm.base);
63343	},
63344
63345	tooltipPosition: function() {
63346		var vm = this._view;
63347		return {
63348			x: vm.x,
63349			y: vm.y
63350		};
63351	}
63352});
63353
63354var elements = {};
63355var Arc = element_arc;
63356var Line = element_line;
63357var Point = element_point;
63358var Rectangle = element_rectangle;
63359elements.Arc = Arc;
63360elements.Line = Line;
63361elements.Point = Point;
63362elements.Rectangle = Rectangle;
63363
63364var resolve$1 = helpers$1.options.resolve;
63365
63366core_defaults._set('bar', {
63367	hover: {
63368		mode: 'label'
63369	},
63370
63371	scales: {
63372		xAxes: [{
63373			type: 'category',
63374			categoryPercentage: 0.8,
63375			barPercentage: 0.9,
63376			offset: true,
63377			gridLines: {
63378				offsetGridLines: true
63379			}
63380		}],
63381
63382		yAxes: [{
63383			type: 'linear'
63384		}]
63385	}
63386});
63387
63388/**
63389 * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap.
63390 * @private
63391 */
63392function computeMinSampleSize(scale, pixels) {
63393	var min = scale.isHorizontal() ? scale.width : scale.height;
63394	var ticks = scale.getTicks();
63395	var prev, curr, i, ilen;
63396
63397	for (i = 1, ilen = pixels.length; i < ilen; ++i) {
63398		min = Math.min(min, Math.abs(pixels[i] - pixels[i - 1]));
63399	}
63400
63401	for (i = 0, ilen = ticks.length; i < ilen; ++i) {
63402		curr = scale.getPixelForTick(i);
63403		min = i > 0 ? Math.min(min, curr - prev) : min;
63404		prev = curr;
63405	}
63406
63407	return min;
63408}
63409
63410/**
63411 * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null,
63412 * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This
63413 * mode currently always generates bars equally sized (until we introduce scriptable options?).
63414 * @private
63415 */
63416function computeFitCategoryTraits(index, ruler, options) {
63417	var thickness = options.barThickness;
63418	var count = ruler.stackCount;
63419	var curr = ruler.pixels[index];
63420	var size, ratio;
63421
63422	if (helpers$1.isNullOrUndef(thickness)) {
63423		size = ruler.min * options.categoryPercentage;
63424		ratio = options.barPercentage;
63425	} else {
63426		// When bar thickness is enforced, category and bar percentages are ignored.
63427		// Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%')
63428		// and deprecate barPercentage since this value is ignored when thickness is absolute.
63429		size = thickness * count;
63430		ratio = 1;
63431	}
63432
63433	return {
63434		chunk: size / count,
63435		ratio: ratio,
63436		start: curr - (size / 2)
63437	};
63438}
63439
63440/**
63441 * Computes an "optimal" category that globally arranges bars side by side (no gap when
63442 * percentage options are 1), based on the previous and following categories. This mode
63443 * generates bars with different widths when data are not evenly spaced.
63444 * @private
63445 */
63446function computeFlexCategoryTraits(index, ruler, options) {
63447	var pixels = ruler.pixels;
63448	var curr = pixels[index];
63449	var prev = index > 0 ? pixels[index - 1] : null;
63450	var next = index < pixels.length - 1 ? pixels[index + 1] : null;
63451	var percent = options.categoryPercentage;
63452	var start, size;
63453
63454	if (prev === null) {
63455		// first data: its size is double based on the next point or,
63456		// if it's also the last data, we use the scale size.
63457		prev = curr - (next === null ? ruler.end - ruler.start : next - curr);
63458	}
63459
63460	if (next === null) {
63461		// last data: its size is also double based on the previous point.
63462		next = curr + curr - prev;
63463	}
63464
63465	start = curr - (curr - Math.min(prev, next)) / 2 * percent;
63466	size = Math.abs(next - prev) / 2 * percent;
63467
63468	return {
63469		chunk: size / ruler.stackCount,
63470		ratio: options.barPercentage,
63471		start: start
63472	};
63473}
63474
63475var controller_bar = core_datasetController.extend({
63476
63477	dataElementType: elements.Rectangle,
63478
63479	initialize: function() {
63480		var me = this;
63481		var meta;
63482
63483		core_datasetController.prototype.initialize.apply(me, arguments);
63484
63485		meta = me.getMeta();
63486		meta.stack = me.getDataset().stack;
63487		meta.bar = true;
63488	},
63489
63490	update: function(reset) {
63491		var me = this;
63492		var rects = me.getMeta().data;
63493		var i, ilen;
63494
63495		me._ruler = me.getRuler();
63496
63497		for (i = 0, ilen = rects.length; i < ilen; ++i) {
63498			me.updateElement(rects[i], i, reset);
63499		}
63500	},
63501
63502	updateElement: function(rectangle, index, reset) {
63503		var me = this;
63504		var meta = me.getMeta();
63505		var dataset = me.getDataset();
63506		var options = me._resolveElementOptions(rectangle, index);
63507
63508		rectangle._xScale = me.getScaleForId(meta.xAxisID);
63509		rectangle._yScale = me.getScaleForId(meta.yAxisID);
63510		rectangle._datasetIndex = me.index;
63511		rectangle._index = index;
63512		rectangle._model = {
63513			backgroundColor: options.backgroundColor,
63514			borderColor: options.borderColor,
63515			borderSkipped: options.borderSkipped,
63516			borderWidth: options.borderWidth,
63517			datasetLabel: dataset.label,
63518			label: me.chart.data.labels[index]
63519		};
63520
63521		me._updateElementGeometry(rectangle, index, reset);
63522
63523		rectangle.pivot();
63524	},
63525
63526	/**
63527	 * @private
63528	 */
63529	_updateElementGeometry: function(rectangle, index, reset) {
63530		var me = this;
63531		var model = rectangle._model;
63532		var vscale = me._getValueScale();
63533		var base = vscale.getBasePixel();
63534		var horizontal = vscale.isHorizontal();
63535		var ruler = me._ruler || me.getRuler();
63536		var vpixels = me.calculateBarValuePixels(me.index, index);
63537		var ipixels = me.calculateBarIndexPixels(me.index, index, ruler);
63538
63539		model.horizontal = horizontal;
63540		model.base = reset ? base : vpixels.base;
63541		model.x = horizontal ? reset ? base : vpixels.head : ipixels.center;
63542		model.y = horizontal ? ipixels.center : reset ? base : vpixels.head;
63543		model.height = horizontal ? ipixels.size : undefined;
63544		model.width = horizontal ? undefined : ipixels.size;
63545	},
63546
63547	/**
63548	 * Returns the stacks based on groups and bar visibility.
63549	 * @param {number} [last] - The dataset index
63550	 * @returns {string[]} The list of stack IDs
63551	 * @private
63552	 */
63553	_getStacks: function(last) {
63554		var me = this;
63555		var chart = me.chart;
63556		var scale = me._getIndexScale();
63557		var stacked = scale.options.stacked;
63558		var ilen = last === undefined ? chart.data.datasets.length : last + 1;
63559		var stacks = [];
63560		var i, meta;
63561
63562		for (i = 0; i < ilen; ++i) {
63563			meta = chart.getDatasetMeta(i);
63564			if (meta.bar && chart.isDatasetVisible(i) &&
63565				(stacked === false ||
63566				(stacked === true && stacks.indexOf(meta.stack) === -1) ||
63567				(stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) {
63568				stacks.push(meta.stack);
63569			}
63570		}
63571
63572		return stacks;
63573	},
63574
63575	/**
63576	 * Returns the effective number of stacks based on groups and bar visibility.
63577	 * @private
63578	 */
63579	getStackCount: function() {
63580		return this._getStacks().length;
63581	},
63582
63583	/**
63584	 * Returns the stack index for the given dataset based on groups and bar visibility.
63585	 * @param {number} [datasetIndex] - The dataset index
63586	 * @param {string} [name] - The stack name to find
63587	 * @returns {number} The stack index
63588	 * @private
63589	 */
63590	getStackIndex: function(datasetIndex, name) {
63591		var stacks = this._getStacks(datasetIndex);
63592		var index = (name !== undefined)
63593			? stacks.indexOf(name)
63594			: -1; // indexOf returns -1 if element is not present
63595
63596		return (index === -1)
63597			? stacks.length - 1
63598			: index;
63599	},
63600
63601	/**
63602	 * @private
63603	 */
63604	getRuler: function() {
63605		var me = this;
63606		var scale = me._getIndexScale();
63607		var stackCount = me.getStackCount();
63608		var datasetIndex = me.index;
63609		var isHorizontal = scale.isHorizontal();
63610		var start = isHorizontal ? scale.left : scale.top;
63611		var end = start + (isHorizontal ? scale.width : scale.height);
63612		var pixels = [];
63613		var i, ilen, min;
63614
63615		for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) {
63616			pixels.push(scale.getPixelForValue(null, i, datasetIndex));
63617		}
63618
63619		min = helpers$1.isNullOrUndef(scale.options.barThickness)
63620			? computeMinSampleSize(scale, pixels)
63621			: -1;
63622
63623		return {
63624			min: min,
63625			pixels: pixels,
63626			start: start,
63627			end: end,
63628			stackCount: stackCount,
63629			scale: scale
63630		};
63631	},
63632
63633	/**
63634	 * Note: pixel values are not clamped to the scale area.
63635	 * @private
63636	 */
63637	calculateBarValuePixels: function(datasetIndex, index) {
63638		var me = this;
63639		var chart = me.chart;
63640		var meta = me.getMeta();
63641		var scale = me._getValueScale();
63642		var isHorizontal = scale.isHorizontal();
63643		var datasets = chart.data.datasets;
63644		var value = +scale.getRightValue(datasets[datasetIndex].data[index]);
63645		var minBarLength = scale.options.minBarLength;
63646		var stacked = scale.options.stacked;
63647		var stack = meta.stack;
63648		var start = 0;
63649		var i, imeta, ivalue, base, head, size;
63650
63651		if (stacked || (stacked === undefined && stack !== undefined)) {
63652			for (i = 0; i < datasetIndex; ++i) {
63653				imeta = chart.getDatasetMeta(i);
63654
63655				if (imeta.bar &&
63656					imeta.stack === stack &&
63657					imeta.controller._getValueScaleId() === scale.id &&
63658					chart.isDatasetVisible(i)) {
63659
63660					ivalue = +scale.getRightValue(datasets[i].data[index]);
63661					if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) {
63662						start += ivalue;
63663					}
63664				}
63665			}
63666		}
63667
63668		base = scale.getPixelForValue(start);
63669		head = scale.getPixelForValue(start + value);
63670		size = head - base;
63671
63672		if (minBarLength !== undefined && Math.abs(size) < minBarLength) {
63673			size = minBarLength;
63674			if (value >= 0 && !isHorizontal || value < 0 && isHorizontal) {
63675				head = base - minBarLength;
63676			} else {
63677				head = base + minBarLength;
63678			}
63679		}
63680
63681		return {
63682			size: size,
63683			base: base,
63684			head: head,
63685			center: head + size / 2
63686		};
63687	},
63688
63689	/**
63690	 * @private
63691	 */
63692	calculateBarIndexPixels: function(datasetIndex, index, ruler) {
63693		var me = this;
63694		var options = ruler.scale.options;
63695		var range = options.barThickness === 'flex'
63696			? computeFlexCategoryTraits(index, ruler, options)
63697			: computeFitCategoryTraits(index, ruler, options);
63698
63699		var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack);
63700		var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
63701		var size = Math.min(
63702			helpers$1.valueOrDefault(options.maxBarThickness, Infinity),
63703			range.chunk * range.ratio);
63704
63705		return {
63706			base: center - size / 2,
63707			head: center + size / 2,
63708			center: center,
63709			size: size
63710		};
63711	},
63712
63713	draw: function() {
63714		var me = this;
63715		var chart = me.chart;
63716		var scale = me._getValueScale();
63717		var rects = me.getMeta().data;
63718		var dataset = me.getDataset();
63719		var ilen = rects.length;
63720		var i = 0;
63721
63722		helpers$1.canvas.clipArea(chart.ctx, chart.chartArea);
63723
63724		for (; i < ilen; ++i) {
63725			if (!isNaN(scale.getRightValue(dataset.data[i]))) {
63726				rects[i].draw();
63727			}
63728		}
63729
63730		helpers$1.canvas.unclipArea(chart.ctx);
63731	},
63732
63733	/**
63734	 * @private
63735	 */
63736	_resolveElementOptions: function(rectangle, index) {
63737		var me = this;
63738		var chart = me.chart;
63739		var datasets = chart.data.datasets;
63740		var dataset = datasets[me.index];
63741		var custom = rectangle.custom || {};
63742		var options = chart.options.elements.rectangle;
63743		var values = {};
63744		var i, ilen, key;
63745
63746		// Scriptable options
63747		var context = {
63748			chart: chart,
63749			dataIndex: index,
63750			dataset: dataset,
63751			datasetIndex: me.index
63752		};
63753
63754		var keys = [
63755			'backgroundColor',
63756			'borderColor',
63757			'borderSkipped',
63758			'borderWidth'
63759		];
63760
63761		for (i = 0, ilen = keys.length; i < ilen; ++i) {
63762			key = keys[i];
63763			values[key] = resolve$1([
63764				custom[key],
63765				dataset[key],
63766				options[key]
63767			], context, index);
63768		}
63769
63770		return values;
63771	}
63772});
63773
63774var valueOrDefault$3 = helpers$1.valueOrDefault;
63775var resolve$2 = helpers$1.options.resolve;
63776
63777core_defaults._set('bubble', {
63778	hover: {
63779		mode: 'single'
63780	},
63781
63782	scales: {
63783		xAxes: [{
63784			type: 'linear', // bubble should probably use a linear scale by default
63785			position: 'bottom',
63786			id: 'x-axis-0' // need an ID so datasets can reference the scale
63787		}],
63788		yAxes: [{
63789			type: 'linear',
63790			position: 'left',
63791			id: 'y-axis-0'
63792		}]
63793	},
63794
63795	tooltips: {
63796		callbacks: {
63797			title: function() {
63798				// Title doesn't make sense for scatter since we format the data as a point
63799				return '';
63800			},
63801			label: function(item, data) {
63802				var datasetLabel = data.datasets[item.datasetIndex].label || '';
63803				var dataPoint = data.datasets[item.datasetIndex].data[item.index];
63804				return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')';
63805			}
63806		}
63807	}
63808});
63809
63810var controller_bubble = core_datasetController.extend({
63811	/**
63812	 * @protected
63813	 */
63814	dataElementType: elements.Point,
63815
63816	/**
63817	 * @protected
63818	 */
63819	update: function(reset) {
63820		var me = this;
63821		var meta = me.getMeta();
63822		var points = meta.data;
63823
63824		// Update Points
63825		helpers$1.each(points, function(point, index) {
63826			me.updateElement(point, index, reset);
63827		});
63828	},
63829
63830	/**
63831	 * @protected
63832	 */
63833	updateElement: function(point, index, reset) {
63834		var me = this;
63835		var meta = me.getMeta();
63836		var custom = point.custom || {};
63837		var xScale = me.getScaleForId(meta.xAxisID);
63838		var yScale = me.getScaleForId(meta.yAxisID);
63839		var options = me._resolveElementOptions(point, index);
63840		var data = me.getDataset().data[index];
63841		var dsIndex = me.index;
63842
63843		var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex);
63844		var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex);
63845
63846		point._xScale = xScale;
63847		point._yScale = yScale;
63848		point._options = options;
63849		point._datasetIndex = dsIndex;
63850		point._index = index;
63851		point._model = {
63852			backgroundColor: options.backgroundColor,
63853			borderColor: options.borderColor,
63854			borderWidth: options.borderWidth,
63855			hitRadius: options.hitRadius,
63856			pointStyle: options.pointStyle,
63857			rotation: options.rotation,
63858			radius: reset ? 0 : options.radius,
63859			skip: custom.skip || isNaN(x) || isNaN(y),
63860			x: x,
63861			y: y,
63862		};
63863
63864		point.pivot();
63865	},
63866
63867	/**
63868	 * @protected
63869	 */
63870	setHoverStyle: function(point) {
63871		var model = point._model;
63872		var options = point._options;
63873		var getHoverColor = helpers$1.getHoverColor;
63874
63875		point.$previousStyle = {
63876			backgroundColor: model.backgroundColor,
63877			borderColor: model.borderColor,
63878			borderWidth: model.borderWidth,
63879			radius: model.radius
63880		};
63881
63882		model.backgroundColor = valueOrDefault$3(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
63883		model.borderColor = valueOrDefault$3(options.hoverBorderColor, getHoverColor(options.borderColor));
63884		model.borderWidth = valueOrDefault$3(options.hoverBorderWidth, options.borderWidth);
63885		model.radius = options.radius + options.hoverRadius;
63886	},
63887
63888	/**
63889	 * @private
63890	 */
63891	_resolveElementOptions: function(point, index) {
63892		var me = this;
63893		var chart = me.chart;
63894		var datasets = chart.data.datasets;
63895		var dataset = datasets[me.index];
63896		var custom = point.custom || {};
63897		var options = chart.options.elements.point;
63898		var data = dataset.data[index];
63899		var values = {};
63900		var i, ilen, key;
63901
63902		// Scriptable options
63903		var context = {
63904			chart: chart,
63905			dataIndex: index,
63906			dataset: dataset,
63907			datasetIndex: me.index
63908		};
63909
63910		var keys = [
63911			'backgroundColor',
63912			'borderColor',
63913			'borderWidth',
63914			'hoverBackgroundColor',
63915			'hoverBorderColor',
63916			'hoverBorderWidth',
63917			'hoverRadius',
63918			'hitRadius',
63919			'pointStyle',
63920			'rotation'
63921		];
63922
63923		for (i = 0, ilen = keys.length; i < ilen; ++i) {
63924			key = keys[i];
63925			values[key] = resolve$2([
63926				custom[key],
63927				dataset[key],
63928				options[key]
63929			], context, index);
63930		}
63931
63932		// Custom radius resolution
63933		values.radius = resolve$2([
63934			custom.radius,
63935			data ? data.r : undefined,
63936			dataset.radius,
63937			options.radius
63938		], context, index);
63939
63940		return values;
63941	}
63942});
63943
63944var resolve$3 = helpers$1.options.resolve;
63945var valueOrDefault$4 = helpers$1.valueOrDefault;
63946
63947core_defaults._set('doughnut', {
63948	animation: {
63949		// Boolean - Whether we animate the rotation of the Doughnut
63950		animateRotate: true,
63951		// Boolean - Whether we animate scaling the Doughnut from the centre
63952		animateScale: false
63953	},
63954	hover: {
63955		mode: 'single'
63956	},
63957	legendCallback: function(chart) {
63958		var text = [];
63959		text.push('<ul class="' + chart.id + '-legend">');
63960
63961		var data = chart.data;
63962		var datasets = data.datasets;
63963		var labels = data.labels;
63964
63965		if (datasets.length) {
63966			for (var i = 0; i < datasets[0].data.length; ++i) {
63967				text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
63968				if (labels[i]) {
63969					text.push(labels[i]);
63970				}
63971				text.push('</li>');
63972			}
63973		}
63974
63975		text.push('</ul>');
63976		return text.join('');
63977	},
63978	legend: {
63979		labels: {
63980			generateLabels: function(chart) {
63981				var data = chart.data;
63982				if (data.labels.length && data.datasets.length) {
63983					return data.labels.map(function(label, i) {
63984						var meta = chart.getDatasetMeta(0);
63985						var ds = data.datasets[0];
63986						var arc = meta.data[i];
63987						var custom = arc && arc.custom || {};
63988						var arcOpts = chart.options.elements.arc;
63989						var fill = resolve$3([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i);
63990						var stroke = resolve$3([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i);
63991						var bw = resolve$3([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i);
63992
63993						return {
63994							text: label,
63995							fillStyle: fill,
63996							strokeStyle: stroke,
63997							lineWidth: bw,
63998							hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
63999
64000							// Extra data used for toggling the correct item
64001							index: i
64002						};
64003					});
64004				}
64005				return [];
64006			}
64007		},
64008
64009		onClick: function(e, legendItem) {
64010			var index = legendItem.index;
64011			var chart = this.chart;
64012			var i, ilen, meta;
64013
64014			for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
64015				meta = chart.getDatasetMeta(i);
64016				// toggle visibility of index if exists
64017				if (meta.data[index]) {
64018					meta.data[index].hidden = !meta.data[index].hidden;
64019				}
64020			}
64021
64022			chart.update();
64023		}
64024	},
64025
64026	// The percentage of the chart that we cut out of the middle.
64027	cutoutPercentage: 50,
64028
64029	// The rotation of the chart, where the first data arc begins.
64030	rotation: Math.PI * -0.5,
64031
64032	// The total circumference of the chart.
64033	circumference: Math.PI * 2.0,
64034
64035	// Need to override these to give a nice default
64036	tooltips: {
64037		callbacks: {
64038			title: function() {
64039				return '';
64040			},
64041			label: function(tooltipItem, data) {
64042				var dataLabel = data.labels[tooltipItem.index];
64043				var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
64044
64045				if (helpers$1.isArray(dataLabel)) {
64046					// show value on first line of multiline label
64047					// need to clone because we are changing the value
64048					dataLabel = dataLabel.slice();
64049					dataLabel[0] += value;
64050				} else {
64051					dataLabel += value;
64052				}
64053
64054				return dataLabel;
64055			}
64056		}
64057	}
64058});
64059
64060var controller_doughnut = core_datasetController.extend({
64061
64062	dataElementType: elements.Arc,
64063
64064	linkScales: helpers$1.noop,
64065
64066	// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
64067	getRingIndex: function(datasetIndex) {
64068		var ringIndex = 0;
64069
64070		for (var j = 0; j < datasetIndex; ++j) {
64071			if (this.chart.isDatasetVisible(j)) {
64072				++ringIndex;
64073			}
64074		}
64075
64076		return ringIndex;
64077	},
64078
64079	update: function(reset) {
64080		var me = this;
64081		var chart = me.chart;
64082		var chartArea = chart.chartArea;
64083		var opts = chart.options;
64084		var availableWidth = chartArea.right - chartArea.left;
64085		var availableHeight = chartArea.bottom - chartArea.top;
64086		var minSize = Math.min(availableWidth, availableHeight);
64087		var offset = {x: 0, y: 0};
64088		var meta = me.getMeta();
64089		var arcs = meta.data;
64090		var cutoutPercentage = opts.cutoutPercentage;
64091		var circumference = opts.circumference;
64092		var chartWeight = me._getRingWeight(me.index);
64093		var i, ilen;
64094
64095		// If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
64096		if (circumference < Math.PI * 2.0) {
64097			var startAngle = opts.rotation % (Math.PI * 2.0);
64098			startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
64099			var endAngle = startAngle + circumference;
64100			var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
64101			var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
64102			var contains0 = (startAngle <= 0 && endAngle >= 0) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
64103			var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
64104			var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
64105			var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
64106			var cutout = cutoutPercentage / 100.0;
64107			var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
64108			var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
64109			var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
64110			minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
64111			offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
64112		}
64113
64114		for (i = 0, ilen = arcs.length; i < ilen; ++i) {
64115			arcs[i]._options = me._resolveElementOptions(arcs[i], i);
64116		}
64117
64118		chart.borderWidth = me.getMaxBorderWidth();
64119		chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
64120		chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
64121		chart.radiusLength = (chart.outerRadius - chart.innerRadius) / (me._getVisibleDatasetWeightTotal() || 1);
64122		chart.offsetX = offset.x * chart.outerRadius;
64123		chart.offsetY = offset.y * chart.outerRadius;
64124
64125		meta.total = me.calculateTotal();
64126
vendor: 9,881 bytes, lines 64127-64541
64127		me.outerRadius = chart.outerRadius - chart.radiusLength * me._getRingWeightOffset(me.index);
64128		me.innerRadius = Math.max(me.outerRadius - chart.radiusLength * chartWeight, 0);
64129
64130		for (i = 0, ilen = arcs.length; i < ilen; ++i) {
64131			me.updateElement(arcs[i], i, reset);
64132		}
64133	},
64134
64135	updateElement: function(arc, index, reset) {
64136		var me = this;
64137		var chart = me.chart;
64138		var chartArea = chart.chartArea;
64139		var opts = chart.options;
64140		var animationOpts = opts.animation;
64141		var centerX = (chartArea.left + chartArea.right) / 2;
64142		var centerY = (chartArea.top + chartArea.bottom) / 2;
64143		var startAngle = opts.rotation; // non reset case handled later
64144		var endAngle = opts.rotation; // non reset case handled later
64145		var dataset = me.getDataset();
64146		var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI));
64147		var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius;
64148		var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius;
64149		var options = arc._options || {};
64150
64151		helpers$1.extend(arc, {
64152			// Utility
64153			_datasetIndex: me.index,
64154			_index: index,
64155
64156			// Desired view properties
64157			_model: {
64158				backgroundColor: options.backgroundColor,
64159				borderColor: options.borderColor,
64160				borderWidth: options.borderWidth,
64161				borderAlign: options.borderAlign,
64162				x: centerX + chart.offsetX,
64163				y: centerY + chart.offsetY,
64164				startAngle: startAngle,
64165				endAngle: endAngle,
64166				circumference: circumference,
64167				outerRadius: outerRadius,
64168				innerRadius: innerRadius,
64169				label: helpers$1.valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
64170			}
64171		});
64172
64173		var model = arc._model;
64174
64175		// Set correct angles if not resetting
64176		if (!reset || !animationOpts.animateRotate) {
64177			if (index === 0) {
64178				model.startAngle = opts.rotation;
64179			} else {
64180				model.startAngle = me.getMeta().data[index - 1]._model.endAngle;
64181			}
64182
64183			model.endAngle = model.startAngle + model.circumference;
64184		}
64185
64186		arc.pivot();
64187	},
64188
64189	calculateTotal: function() {
64190		var dataset = this.getDataset();
64191		var meta = this.getMeta();
64192		var total = 0;
64193		var value;
64194
64195		helpers$1.each(meta.data, function(element, index) {
64196			value = dataset.data[index];
64197			if (!isNaN(value) && !element.hidden) {
64198				total += Math.abs(value);
64199			}
64200		});
64201
64202		/* if (total === 0) {
64203			total = NaN;
64204		}*/
64205
64206		return total;
64207	},
64208
64209	calculateCircumference: function(value) {
64210		var total = this.getMeta().total;
64211		if (total > 0 && !isNaN(value)) {
64212			return (Math.PI * 2.0) * (Math.abs(value) / total);
64213		}
64214		return 0;
64215	},
64216
64217	// gets the max border or hover width to properly scale pie charts
64218	getMaxBorderWidth: function(arcs) {
64219		var me = this;
64220		var max = 0;
64221		var chart = me.chart;
64222		var i, ilen, meta, arc, controller, options, borderWidth, hoverWidth;
64223
64224		if (!arcs) {
64225			// Find the outmost visible dataset
64226			for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
64227				if (chart.isDatasetVisible(i)) {
64228					meta = chart.getDatasetMeta(i);
64229					arcs = meta.data;
64230					if (i !== me.index) {
64231						controller = meta.controller;
64232					}
64233					break;
64234				}
64235			}
64236		}
64237
64238		if (!arcs) {
64239			return 0;
64240		}
64241
64242		for (i = 0, ilen = arcs.length; i < ilen; ++i) {
64243			arc = arcs[i];
64244			options = controller ? controller._resolveElementOptions(arc, i) : arc._options;
64245			if (options.borderAlign !== 'inner') {
64246				borderWidth = options.borderWidth;
64247				hoverWidth = options.hoverBorderWidth;
64248
64249				max = borderWidth > max ? borderWidth : max;
64250				max = hoverWidth > max ? hoverWidth : max;
64251			}
64252		}
64253		return max;
64254	},
64255
64256	/**
64257	 * @protected
64258	 */
64259	setHoverStyle: function(arc) {
64260		var model = arc._model;
64261		var options = arc._options;
64262		var getHoverColor = helpers$1.getHoverColor;
64263
64264		arc.$previousStyle = {
64265			backgroundColor: model.backgroundColor,
64266			borderColor: model.borderColor,
64267			borderWidth: model.borderWidth,
64268		};
64269
64270		model.backgroundColor = valueOrDefault$4(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
64271		model.borderColor = valueOrDefault$4(options.hoverBorderColor, getHoverColor(options.borderColor));
64272		model.borderWidth = valueOrDefault$4(options.hoverBorderWidth, options.borderWidth);
64273	},
64274
64275	/**
64276	 * @private
64277	 */
64278	_resolveElementOptions: function(arc, index) {
64279		var me = this;
64280		var chart = me.chart;
64281		var dataset = me.getDataset();
64282		var custom = arc.custom || {};
64283		var options = chart.options.elements.arc;
64284		var values = {};
64285		var i, ilen, key;
64286
64287		// Scriptable options
64288		var context = {
64289			chart: chart,
64290			dataIndex: index,
64291			dataset: dataset,
64292			datasetIndex: me.index
64293		};
64294
64295		var keys = [
64296			'backgroundColor',
64297			'borderColor',
64298			'borderWidth',
64299			'borderAlign',
64300			'hoverBackgroundColor',
64301			'hoverBorderColor',
64302			'hoverBorderWidth',
64303		];
64304
64305		for (i = 0, ilen = keys.length; i < ilen; ++i) {
64306			key = keys[i];
64307			values[key] = resolve$3([
64308				custom[key],
64309				dataset[key],
64310				options[key]
64311			], context, index);
64312		}
64313
64314		return values;
64315	},
64316
64317	/**
64318	 * Get radius length offset of the dataset in relation to the visible datasets weights. This allows determining the inner and outer radius correctly
64319	 * @private
64320	 */
64321	_getRingWeightOffset: function(datasetIndex) {
64322		var ringWeightOffset = 0;
64323
64324		for (var i = 0; i < datasetIndex; ++i) {
64325			if (this.chart.isDatasetVisible(i)) {
64326				ringWeightOffset += this._getRingWeight(i);
64327			}
64328		}
64329
64330		return ringWeightOffset;
64331	},
64332
64333	/**
64334	 * @private
64335	 */
64336	_getRingWeight: function(dataSetIndex) {
64337		return Math.max(valueOrDefault$4(this.chart.data.datasets[dataSetIndex].weight, 1), 0);
64338	},
64339
64340	/**
64341	 * Returns the sum of all visibile data set weights.  This value can be 0.
64342	 * @private
64343	 */
64344	_getVisibleDatasetWeightTotal: function() {
64345		return this._getRingWeightOffset(this.chart.data.datasets.length);
64346	}
64347});
64348
64349core_defaults._set('horizontalBar', {
64350	hover: {
64351		mode: 'index',
64352		axis: 'y'
64353	},
64354
64355	scales: {
64356		xAxes: [{
64357			type: 'linear',
64358			position: 'bottom'
64359		}],
64360
64361		yAxes: [{
64362			type: 'category',
64363			position: 'left',
64364			categoryPercentage: 0.8,
64365			barPercentage: 0.9,
64366			offset: true,
64367			gridLines: {
64368				offsetGridLines: true
64369			}
64370		}]
64371	},
64372
64373	elements: {
64374		rectangle: {
64375			borderSkipped: 'left'
64376		}
64377	},
64378
64379	tooltips: {
64380		mode: 'index',
64381		axis: 'y'
64382	}
64383});
64384
64385var controller_horizontalBar = controller_bar.extend({
64386	/**
64387	 * @private
64388	 */
64389	_getValueScaleId: function() {
64390		return this.getMeta().xAxisID;
64391	},
64392
64393	/**
64394	 * @private
64395	 */
64396	_getIndexScaleId: function() {
64397		return this.getMeta().yAxisID;
64398	}
64399});
64400
64401var valueOrDefault$5 = helpers$1.valueOrDefault;
64402var resolve$4 = helpers$1.options.resolve;
64403var isPointInArea = helpers$1.canvas._isPointInArea;
64404
64405core_defaults._set('line', {
64406	showLines: true,
64407	spanGaps: false,
64408
64409	hover: {
64410		mode: 'label'
64411	},
64412
64413	scales: {
64414		xAxes: [{
64415			type: 'category',
64416			id: 'x-axis-0'
64417		}],
64418		yAxes: [{
64419			type: 'linear',
64420			id: 'y-axis-0'
64421		}]
64422	}
64423});
64424
64425function lineEnabled(dataset, options) {
64426	return valueOrDefault$5(dataset.showLine, options.showLines);
64427}
64428
64429var controller_line = core_datasetController.extend({
64430
64431	datasetElementType: elements.Line,
64432
64433	dataElementType: elements.Point,
64434
64435	update: function(reset) {
64436		var me = this;
64437		var meta = me.getMeta();
64438		var line = meta.dataset;
64439		var points = meta.data || [];
64440		var scale = me.getScaleForId(meta.yAxisID);
64441		var dataset = me.getDataset();
64442		var showLine = lineEnabled(dataset, me.chart.options);
64443		var i, ilen;
64444
64445		// Update Line
64446		if (showLine) {
64447			// Compatibility: If the properties are defined with only the old name, use those values
64448			if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
64449				dataset.lineTension = dataset.tension;
64450			}
64451
64452			// Utility
64453			line._scale = scale;
64454			line._datasetIndex = me.index;
64455			// Data
64456			line._children = points;
64457			// Model
64458			line._model = me._resolveLineOptions(line);
64459
64460			line.pivot();
64461		}
64462
64463		// Update Points
64464		for (i = 0, ilen = points.length; i < ilen; ++i) {
64465			me.updateElement(points[i], i, reset);
64466		}
64467
64468		if (showLine && line._model.tension !== 0) {
64469			me.updateBezierControlPoints();
64470		}
64471
64472		// Now pivot the point for animation
64473		for (i = 0, ilen = points.length; i < ilen; ++i) {
64474			points[i].pivot();
64475		}
64476	},
64477
64478	updateElement: function(point, index, reset) {
64479		var me = this;
64480		var meta = me.getMeta();
64481		var custom = point.custom || {};
64482		var dataset = me.getDataset();
64483		var datasetIndex = me.index;
64484		var value = dataset.data[index];
64485		var yScale = me.getScaleForId(meta.yAxisID);
64486		var xScale = me.getScaleForId(meta.xAxisID);
64487		var lineModel = meta.dataset._model;
64488		var x, y;
64489
64490		var options = me._resolvePointOptions(point, index);
64491
64492		x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex);
64493		y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
64494
64495		// Utility
64496		point._xScale = xScale;
64497		point._yScale = yScale;
64498		point._options = options;
64499		point._datasetIndex = datasetIndex;
64500		point._index = index;
64501
64502		// Desired view properties
64503		point._model = {
64504			x: x,
64505			y: y,
64506			skip: custom.skip || isNaN(x) || isNaN(y),
64507			// Appearance
64508			radius: options.radius,
64509			pointStyle: options.pointStyle,
64510			rotation: options.rotation,
64511			backgroundColor: options.backgroundColor,
64512			borderColor: options.borderColor,
64513			borderWidth: options.borderWidth,
64514			tension: valueOrDefault$5(custom.tension, lineModel ? lineModel.tension : 0),
64515			steppedLine: lineModel ? lineModel.steppedLine : false,
64516			// Tooltip
64517			hitRadius: options.hitRadius
64518		};
64519	},
64520
64521	/**
64522	 * @private
64523	 */
64524	_resolvePointOptions: function(element, index) {
64525		var me = this;
64526		var chart = me.chart;
64527		var dataset = chart.data.datasets[me.index];
64528		var custom = element.custom || {};
64529		var options = chart.options.elements.point;
64530		var values = {};
64531		var i, ilen, key;
64532
64533		// Scriptable options
64534		var context = {
64535			chart: chart,
64536			dataIndex: index,
64537			dataset: dataset,
64538			datasetIndex: me.index
64539		};
64540
64541		var ELEMENT_OPTIONS = {
64542			backgroundColor: 'pointBackgroundColor',
64543			borderColor: 'pointBorderColor',
64544			borderWidth: 'pointBorderWidth',
64545			hitRadius: 'pointHitRadius',
64546			hoverBackgroundColor: 'pointHoverBackgroundColor',
64547			hoverBorderColor: 'pointHoverBorderColor',
64548			hoverBorderWidth: 'pointHoverBorderWidth',
64549			hoverRadius: 'pointHoverRadius',
64550			pointStyle: 'pointStyle',
64551			radius: 'pointRadius',
64552			rotation: 'pointRotation'
64553		};
64554		var keys = Object.keys(ELEMENT_OPTIONS);
64555
64556		for (i = 0, ilen = keys.length; i < ilen; ++i) {
64557			key = keys[i];
64558			values[key] = resolve$4([
64559				custom[key],
64560				dataset[ELEMENT_OPTIONS[key]],
64561				dataset[key],
64562				options[key]
64563			], context, index);
64564		}
64565
64566		return values;
64567	},
64568
64569	/**
64570	 * @private
64571	 */
64572	_resolveLineOptions: function(element) {
64573		var me = this;
64574		var chart = me.chart;
64575		var dataset = chart.data.datasets[me.index];
64576		var custom = element.custom || {};
64577		var options = chart.options;
64578		var elementOptions = options.elements.line;
64579		var values = {};
64580		var i, ilen, key;
64581
64582		var keys = [
64583			'backgroundColor',
64584			'borderWidth',
64585			'borderColor',
64586			'borderCapStyle',
64587			'borderDash',
64588			'borderDashOffset',
64589			'borderJoinStyle',
64590			'fill',
64591			'cubicInterpolationMode'
64592		];
64593
64594		for (i = 0, ilen = keys.length; i < ilen; ++i) {
64595			key = keys[i];
64596			values[key] = resolve$4([
64597				custom[key],
64598				dataset[key],
64599				elementOptions[key]
64600			]);
64601		}
64602
64603		// The default behavior of lines is to break at null values, according
64604		// to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
64605		// This option gives lines the ability to span gaps
64606		values.spanGaps = valueOrDefault$5(dataset.spanGaps, options.spanGaps);
64607		values.tension = valueOrDefault$5(dataset.lineTension, elementOptions.tension);
64608		values.steppedLine = resolve$4([custom.steppedLine, dataset.steppedLine, elementOptions.stepped]);
64609
64610		return values;
64611	},
64612
64613	calculatePointY: function(value, index, datasetIndex) {
64614		var me = this;
64615		var chart = me.chart;
64616		var meta = me.getMeta();
64617		var yScale = me.getScaleForId(meta.yAxisID);
64618		var sumPos = 0;
64619		var sumNeg = 0;
64620		var i, ds, dsMeta;
64621
64622		if (yScale.options.stacked) {
64623			for (i = 0; i < datasetIndex; i++) {
64624				ds = chart.data.datasets[i];
64625				dsMeta = chart.getDatasetMeta(i);
64626				if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
64627					var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
64628					if (stackedRightValue < 0) {
64629						sumNeg += stackedRightValue || 0;
64630					} else {
64631						sumPos += stackedRightValue || 0;
64632					}
64633				}
64634			}
64635
64636			var rightValue = Number(yScale.getRightValue(value));
64637			if (rightValue < 0) {
64638				return yScale.getPixelForValue(sumNeg + rightValue);
64639			}
64640			return yScale.getPixelForValue(sumPos + rightValue);
64641		}
64642
64643		return yScale.getPixelForValue(value);
64644	},
64645
64646	updateBezierControlPoints: function() {
64647		var me = this;
64648		var chart = me.chart;
64649		var meta = me.getMeta();
64650		var lineModel = meta.dataset._model;
64651		var area = chart.chartArea;
64652		var points = meta.data || [];
64653		var i, ilen, model, controlPoints;
64654
64655		// Only consider points that are drawn in case the spanGaps option is used
64656		if (lineModel.spanGaps) {
64657			points = points.filter(function(pt) {
64658				return !pt._model.skip;
64659			});
64660		}
64661
64662		function capControlPoint(pt, min, max) {
64663			return Math.max(Math.min(pt, max), min);
64664		}
64665
64666		if (lineModel.cubicInterpolationMode === 'monotone') {
64667			helpers$1.splineCurveMonotone(points);
64668		} else {
64669			for (i = 0, ilen = points.length; i < ilen; ++i) {
64670				model = points[i]._model;
64671				controlPoints = helpers$1.splineCurve(
64672					helpers$1.previousItem(points, i)._model,
64673					model,
64674					helpers$1.nextItem(points, i)._model,
64675					lineModel.tension
64676				);
64677				model.controlPointPreviousX = controlPoints.previous.x;
64678				model.controlPointPreviousY = controlPoints.previous.y;
64679				model.controlPointNextX = controlPoints.next.x;
64680				model.controlPointNextY = controlPoints.next.y;
64681			}
64682		}
64683
64684		if (chart.options.elements.line.capBezierPoints) {
64685			for (i = 0, ilen = points.length; i < ilen; ++i) {
64686				model = points[i]._model;
64687				if (isPointInArea(model, area)) {
64688					if (i > 0 && isPointInArea(points[i - 1]._model, area)) {
64689						model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);
64690						model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
64691					}
64692					if (i < points.length - 1 && isPointInArea(points[i + 1]._model, area)) {
64693						model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);
64694						model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);
64695					}
64696				}
64697			}
64698		}
64699	},
64700
64701	draw: function() {
64702		var me = this;
64703		var chart = me.chart;
64704		var meta = me.getMeta();
64705		var points = meta.data || [];
64706		var area = chart.chartArea;
64707		var ilen = points.length;
64708		var halfBorderWidth;
64709		var i = 0;
64710
64711		if (lineEnabled(me.getDataset(), chart.options)) {
64712			halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2;
64713
64714			helpers$1.canvas.clipArea(chart.ctx, {
64715				left: area.left,
64716				right: area.right,
64717				top: area.top - halfBorderWidth,
64718				bottom: area.bottom + halfBorderWidth
64719			});
64720
64721			meta.dataset.draw();
64722
64723			helpers$1.canvas.unclipArea(chart.ctx);
64724		}
64725
64726		// Draw the points
64727		for (; i < ilen; ++i) {
64728			points[i].draw(area);
64729		}
64730	},
64731
64732	/**
64733	 * @protected
64734	 */
64735	setHoverStyle: function(point) {
64736		var model = point._model;
64737		var options = point._options;
64738		var getHoverColor = helpers$1.getHoverColor;
64739
64740		point.$previousStyle = {
64741			backgroundColor: model.backgroundColor,
64742			borderColor: model.borderColor,
64743			borderWidth: model.borderWidth,
64744			radius: model.radius
64745		};
64746
64747		model.backgroundColor = valueOrDefault$5(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
64748		model.borderColor = valueOrDefault$5(options.hoverBorderColor, getHoverColor(options.borderColor));
64749		model.borderWidth = valueOrDefault$5(options.hoverBorderWidth, options.borderWidth);
64750		model.radius = valueOrDefault$5(options.hoverRadius, options.radius);
64751	},
64752});
64753
64754var resolve$5 = helpers$1.options.resolve;
64755
64756core_defaults._set('polarArea', {
64757	scale: {
64758		type: 'radialLinear',
64759		angleLines: {
64760			display: false
64761		},
64762		gridLines: {
64763			circular: true
64764		},
64765		pointLabels: {
64766			display: false
64767		},
64768		ticks: {
64769			beginAtZero: true
64770		}
64771	},
64772
64773	// Boolean - Whether to animate the rotation of the chart
64774	animation: {
64775		animateRotate: true,
64776		animateScale: true
64777	},
64778
64779	startAngle: -0.5 * Math.PI,
64780	legendCallback: function(chart) {
64781		var text = [];
64782		text.push('<ul class="' + chart.id + '-legend">');
64783
64784		var data = chart.data;
64785		var datasets = data.datasets;
64786		var labels = data.labels;
64787
64788		if (datasets.length) {
64789			for (var i = 0; i < datasets[0].data.length; ++i) {
64790				text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
64791				if (labels[i]) {
64792					text.push(labels[i]);
64793				}
64794				text.push('</li>');
64795			}
64796		}
64797
64798		text.push('</ul>');
64799		return text.join('');
64800	},
64801	legend: {
64802		labels: {
64803			generateLabels: function(chart) {
64804				var data = chart.data;
64805				if (data.labels.length && data.datasets.length) {
64806					return data.labels.map(function(label, i) {
64807						var meta = chart.getDatasetMeta(0);
64808						var ds = data.datasets[0];
64809						var arc = meta.data[i];
64810						var custom = arc.custom || {};
64811						var arcOpts = chart.options.elements.arc;
64812						var fill = resolve$5([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i);
64813						var stroke = resolve$5([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i);
64814						var bw = resolve$5([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i);
64815
64816						return {
64817							text: label,
64818							fillStyle: fill,
64819							strokeStyle: stroke,
64820							lineWidth: bw,
64821							hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
64822
64823							// Extra data used for toggling the correct item
64824							index: i
64825						};
64826					});
64827				}
64828				return [];
64829			}
64830		},
64831
64832		onClick: function(e, legendItem) {
64833			var index = legendItem.index;
64834			var chart = this.chart;
64835			var i, ilen, meta;
64836
64837			for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
64838				meta = chart.getDatasetMeta(i);
64839				meta.data[index].hidden = !meta.data[index].hidden;
64840			}
64841
64842			chart.update();
64843		}
64844	},
64845
64846	// Need to override these to give a nice default
64847	tooltips: {
64848		callbacks: {
64849			title: function() {
64850				return '';
64851			},
64852			label: function(item, data) {
64853				return data.labels[item.index] + ': ' + item.yLabel;
64854			}
64855		}
64856	}
64857});
64858
vendor: 20,646 bytes, lines 64859-65598
64859var controller_polarArea = core_datasetController.extend({
64860
64861	dataElementType: elements.Arc,
64862
64863	linkScales: helpers$1.noop,
64864
64865	update: function(reset) {
64866		var me = this;
64867		var dataset = me.getDataset();
64868		var meta = me.getMeta();
64869		var start = me.chart.options.startAngle || 0;
64870		var starts = me._starts = [];
64871		var angles = me._angles = [];
64872		var arcs = meta.data;
64873		var i, ilen, angle;
64874
64875		me._updateRadius();
64876
64877		meta.count = me.countVisibleElements();
64878
64879		for (i = 0, ilen = dataset.data.length; i < ilen; i++) {
64880			starts[i] = start;
64881			angle = me._computeAngle(i);
64882			angles[i] = angle;
64883			start += angle;
64884		}
64885
64886		for (i = 0, ilen = arcs.length; i < ilen; ++i) {
64887			arcs[i]._options = me._resolveElementOptions(arcs[i], i);
64888			me.updateElement(arcs[i], i, reset);
64889		}
64890	},
64891
64892	/**
64893	 * @private
64894	 */
64895	_updateRadius: function() {
64896		var me = this;
64897		var chart = me.chart;
64898		var chartArea = chart.chartArea;
64899		var opts = chart.options;
64900		var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
64901
64902		chart.outerRadius = Math.max(minSize / 2, 0);
64903		chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
64904		chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
64905
64906		me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);
64907		me.innerRadius = me.outerRadius - chart.radiusLength;
64908	},
64909
64910	updateElement: function(arc, index, reset) {
64911		var me = this;
64912		var chart = me.chart;
64913		var dataset = me.getDataset();
64914		var opts = chart.options;
64915		var animationOpts = opts.animation;
64916		var scale = chart.scale;
64917		var labels = chart.data.labels;
64918
64919		var centerX = scale.xCenter;
64920		var centerY = scale.yCenter;
64921
64922		// var negHalfPI = -0.5 * Math.PI;
64923		var datasetStartAngle = opts.startAngle;
64924		var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
64925		var startAngle = me._starts[index];
64926		var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]);
64927
64928		var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
64929		var options = arc._options || {};
64930
64931		helpers$1.extend(arc, {
64932			// Utility
64933			_datasetIndex: me.index,
64934			_index: index,
64935			_scale: scale,
64936
64937			// Desired view properties
64938			_model: {
64939				backgroundColor: options.backgroundColor,
64940				borderColor: options.borderColor,
64941				borderWidth: options.borderWidth,
64942				borderAlign: options.borderAlign,
64943				x: centerX,
64944				y: centerY,
64945				innerRadius: 0,
64946				outerRadius: reset ? resetRadius : distance,
64947				startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,
64948				endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,
64949				label: helpers$1.valueAtIndexOrDefault(labels, index, labels[index])
64950			}
64951		});
64952
64953		arc.pivot();
64954	},
64955
64956	countVisibleElements: function() {
64957		var dataset = this.getDataset();
64958		var meta = this.getMeta();
64959		var count = 0;
64960
64961		helpers$1.each(meta.data, function(element, index) {
64962			if (!isNaN(dataset.data[index]) && !element.hidden) {
64963				count++;
64964			}
64965		});
64966
64967		return count;
64968	},
64969
64970	/**
64971	 * @protected
64972	 */
64973	setHoverStyle: function(arc) {
64974		var model = arc._model;
64975		var options = arc._options;
64976		var getHoverColor = helpers$1.getHoverColor;
64977		var valueOrDefault = helpers$1.valueOrDefault;
64978
64979		arc.$previousStyle = {
64980			backgroundColor: model.backgroundColor,
64981			borderColor: model.borderColor,
64982			borderWidth: model.borderWidth,
64983		};
64984
64985		model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
64986		model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor));
64987		model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth);
64988	},
64989
64990	/**
64991	 * @private
64992	 */
64993	_resolveElementOptions: function(arc, index) {
64994		var me = this;
64995		var chart = me.chart;
64996		var dataset = me.getDataset();
64997		var custom = arc.custom || {};
64998		var options = chart.options.elements.arc;
64999		var values = {};
65000		var i, ilen, key;
65001
65002		// Scriptable options
65003		var context = {
65004			chart: chart,
65005			dataIndex: index,
65006			dataset: dataset,
65007			datasetIndex: me.index
65008		};
65009
65010		var keys = [
65011			'backgroundColor',
65012			'borderColor',
65013			'borderWidth',
65014			'borderAlign',
65015			'hoverBackgroundColor',
65016			'hoverBorderColor',
65017			'hoverBorderWidth',
65018		];
65019
65020		for (i = 0, ilen = keys.length; i < ilen; ++i) {
65021			key = keys[i];
65022			values[key] = resolve$5([
65023				custom[key],
65024				dataset[key],
65025				options[key]
65026			], context, index);
65027		}
65028
65029		return values;
65030	},
65031
65032	/**
65033	 * @private
65034	 */
65035	_computeAngle: function(index) {
65036		var me = this;
65037		var count = this.getMeta().count;
65038		var dataset = me.getDataset();
65039		var meta = me.getMeta();
65040
65041		if (isNaN(dataset.data[index]) || meta.data[index].hidden) {
65042			return 0;
65043		}
65044
65045		// Scriptable options
65046		var context = {
65047			chart: me.chart,
65048			dataIndex: index,
65049			dataset: dataset,
65050			datasetIndex: me.index
65051		};
65052
65053		return resolve$5([
65054			me.chart.options.elements.arc.angle,
65055			(2 * Math.PI) / count
65056		], context, index);
65057	}
65058});
65059
65060core_defaults._set('pie', helpers$1.clone(core_defaults.doughnut));
65061core_defaults._set('pie', {
65062	cutoutPercentage: 0
65063});
65064
65065// Pie charts are Doughnut chart with different defaults
65066var controller_pie = controller_doughnut;
65067
65068var valueOrDefault$6 = helpers$1.valueOrDefault;
65069var resolve$6 = helpers$1.options.resolve;
65070
65071core_defaults._set('radar', {
65072	scale: {
65073		type: 'radialLinear'
65074	},
65075	elements: {
65076		line: {
65077			tension: 0 // no bezier in radar
65078		}
65079	}
65080});
65081
65082var controller_radar = core_datasetController.extend({
65083
65084	datasetElementType: elements.Line,
65085
65086	dataElementType: elements.Point,
65087
65088	linkScales: helpers$1.noop,
65089
65090	update: function(reset) {
65091		var me = this;
65092		var meta = me.getMeta();
65093		var line = meta.dataset;
65094		var points = meta.data || [];
65095		var scale = me.chart.scale;
65096		var dataset = me.getDataset();
65097		var i, ilen;
65098
65099		// Compatibility: If the properties are defined with only the old name, use those values
65100		if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
65101			dataset.lineTension = dataset.tension;
65102		}
65103
65104		// Utility
65105		line._scale = scale;
65106		line._datasetIndex = me.index;
65107		// Data
65108		line._children = points;
65109		line._loop = true;
65110		// Model
65111		line._model = me._resolveLineOptions(line);
65112
65113		line.pivot();
65114
65115		// Update Points
65116		for (i = 0, ilen = points.length; i < ilen; ++i) {
65117			me.updateElement(points[i], i, reset);
65118		}
65119
65120		// Update bezier control points
65121		me.updateBezierControlPoints();
65122
65123		// Now pivot the point for animation
65124		for (i = 0, ilen = points.length; i < ilen; ++i) {
65125			points[i].pivot();
65126		}
65127	},
65128
65129	updateElement: function(point, index, reset) {
65130		var me = this;
65131		var custom = point.custom || {};
65132		var dataset = me.getDataset();
65133		var scale = me.chart.scale;
65134		var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
65135		var options = me._resolvePointOptions(point, index);
65136		var lineModel = me.getMeta().dataset._model;
65137		var x = reset ? scale.xCenter : pointPosition.x;
65138		var y = reset ? scale.yCenter : pointPosition.y;
65139
65140		// Utility
65141		point._scale = scale;
65142		point._options = options;
65143		point._datasetIndex = me.index;
65144		point._index = index;
65145
65146		// Desired view properties
65147		point._model = {
65148			x: x, // value not used in dataset scale, but we want a consistent API between scales
65149			y: y,
65150			skip: custom.skip || isNaN(x) || isNaN(y),
65151			// Appearance
65152			radius: options.radius,
65153			pointStyle: options.pointStyle,
65154			rotation: options.rotation,
65155			backgroundColor: options.backgroundColor,
65156			borderColor: options.borderColor,
65157			borderWidth: options.borderWidth,
65158			tension: valueOrDefault$6(custom.tension, lineModel ? lineModel.tension : 0),
65159
65160			// Tooltip
65161			hitRadius: options.hitRadius
65162		};
65163	},
65164
65165	/**
65166	 * @private
65167	 */
65168	_resolvePointOptions: function(element, index) {
65169		var me = this;
65170		var chart = me.chart;
65171		var dataset = chart.data.datasets[me.index];
65172		var custom = element.custom || {};
65173		var options = chart.options.elements.point;
65174		var values = {};
65175		var i, ilen, key;
65176
65177		// Scriptable options
65178		var context = {
65179			chart: chart,
65180			dataIndex: index,
65181			dataset: dataset,
65182			datasetIndex: me.index
65183		};
65184
65185		var ELEMENT_OPTIONS = {
65186			backgroundColor: 'pointBackgroundColor',
65187			borderColor: 'pointBorderColor',
65188			borderWidth: 'pointBorderWidth',
65189			hitRadius: 'pointHitRadius',
65190			hoverBackgroundColor: 'pointHoverBackgroundColor',
65191			hoverBorderColor: 'pointHoverBorderColor',
65192			hoverBorderWidth: 'pointHoverBorderWidth',
65193			hoverRadius: 'pointHoverRadius',
65194			pointStyle: 'pointStyle',
65195			radius: 'pointRadius',
65196			rotation: 'pointRotation'
65197		};
65198		var keys = Object.keys(ELEMENT_OPTIONS);
65199
65200		for (i = 0, ilen = keys.length; i < ilen; ++i) {
65201			key = keys[i];
65202			values[key] = resolve$6([
65203				custom[key],
65204				dataset[ELEMENT_OPTIONS[key]],
65205				dataset[key],
65206				options[key]
65207			], context, index);
65208		}
65209
65210		return values;
65211	},
65212
65213	/**
65214	 * @private
65215	 */
65216	_resolveLineOptions: function(element) {
65217		var me = this;
65218		var chart = me.chart;
65219		var dataset = chart.data.datasets[me.index];
65220		var custom = element.custom || {};
65221		var options = chart.options.elements.line;
65222		var values = {};
65223		var i, ilen, key;
65224
65225		var keys = [
65226			'backgroundColor',
65227			'borderWidth',
65228			'borderColor',
65229			'borderCapStyle',
65230			'borderDash',
65231			'borderDashOffset',
65232			'borderJoinStyle',
65233			'fill'
65234		];
65235
65236		for (i = 0, ilen = keys.length; i < ilen; ++i) {
65237			key = keys[i];
65238			values[key] = resolve$6([
65239				custom[key],
65240				dataset[key],
65241				options[key]
65242			]);
65243		}
65244
65245		values.tension = valueOrDefault$6(dataset.lineTension, options.tension);
65246
65247		return values;
65248	},
65249
65250	updateBezierControlPoints: function() {
65251		var me = this;
65252		var meta = me.getMeta();
65253		var area = me.chart.chartArea;
65254		var points = meta.data || [];
65255		var i, ilen, model, controlPoints;
65256
65257		function capControlPoint(pt, min, max) {
65258			return Math.max(Math.min(pt, max), min);
65259		}
65260
65261		for (i = 0, ilen = points.length; i < ilen; ++i) {
65262			model = points[i]._model;
65263			controlPoints = helpers$1.splineCurve(
65264				helpers$1.previousItem(points, i, true)._model,
65265				model,
65266				helpers$1.nextItem(points, i, true)._model,
65267				model.tension
65268			);
65269
65270			// Prevent the bezier going outside of the bounds of the graph
65271			model.controlPointPreviousX = capControlPoint(controlPoints.previous.x, area.left, area.right);
65272			model.controlPointPreviousY = capControlPoint(controlPoints.previous.y, area.top, area.bottom);
65273			model.controlPointNextX = capControlPoint(controlPoints.next.x, area.left, area.right);
65274			model.controlPointNextY = capControlPoint(controlPoints.next.y, area.top, area.bottom);
65275		}
65276	},
65277
65278	setHoverStyle: function(point) {
65279		var model = point._model;
65280		var options = point._options;
65281		var getHoverColor = helpers$1.getHoverColor;
65282
65283		point.$previousStyle = {
65284			backgroundColor: model.backgroundColor,
65285			borderColor: model.borderColor,
65286			borderWidth: model.borderWidth,
65287			radius: model.radius
65288		};
65289
65290		model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
65291		model.borderColor = valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor));
65292		model.borderWidth = valueOrDefault$6(options.hoverBorderWidth, options.borderWidth);
65293		model.radius = valueOrDefault$6(options.hoverRadius, options.radius);
65294	}
65295});
65296
65297core_defaults._set('scatter', {
65298	hover: {
65299		mode: 'single'
65300	},
65301
65302	scales: {
65303		xAxes: [{
65304			id: 'x-axis-1',    // need an ID so datasets can reference the scale
65305			type: 'linear',    // scatter should not use a category axis
65306			position: 'bottom'
65307		}],
65308		yAxes: [{
65309			id: 'y-axis-1',
65310			type: 'linear',
65311			position: 'left'
65312		}]
65313	},
65314
65315	showLines: false,
65316
65317	tooltips: {
65318		callbacks: {
65319			title: function() {
65320				return '';     // doesn't make sense for scatter since data are formatted as a point
65321			},
65322			label: function(item) {
65323				return '(' + item.xLabel + ', ' + item.yLabel + ')';
65324			}
65325		}
65326	}
65327});
65328
65329// Scatter charts use line controllers
65330var controller_scatter = controller_line;
65331
65332// NOTE export a map in which the key represents the controller type, not
65333// the class, and so must be CamelCase in order to be correctly retrieved
65334// by the controller in core.controller.js (`controllers[meta.type]`).
65335
65336var controllers = {
65337	bar: controller_bar,
65338	bubble: controller_bubble,
65339	doughnut: controller_doughnut,
65340	horizontalBar: controller_horizontalBar,
65341	line: controller_line,
65342	polarArea: controller_polarArea,
65343	pie: controller_pie,
65344	radar: controller_radar,
65345	scatter: controller_scatter
65346};
65347
65348/**
65349 * Helper function to get relative position for an event
65350 * @param {Event|IEvent} event - The event to get the position for
65351 * @param {Chart} chart - The chart
65352 * @returns {object} the event position
65353 */
65354function getRelativePosition(e, chart) {
65355	if (e.native) {
65356		return {
65357			x: e.x,
65358			y: e.y
65359		};
65360	}
65361
65362	return helpers$1.getRelativePosition(e, chart);
65363}
65364
65365/**
65366 * Helper function to traverse all of the visible elements in the chart
65367 * @param {Chart} chart - the chart
65368 * @param {function} handler - the callback to execute for each visible item
65369 */
65370function parseVisibleItems(chart, handler) {
65371	var datasets = chart.data.datasets;
65372	var meta, i, j, ilen, jlen;
65373
65374	for (i = 0, ilen = datasets.length; i < ilen; ++i) {
65375		if (!chart.isDatasetVisible(i)) {
65376			continue;
65377		}
65378
65379		meta = chart.getDatasetMeta(i);
65380		for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
65381			var element = meta.data[j];
65382			if (!element._view.skip) {
65383				handler(element);
65384			}
65385		}
65386	}
65387}
65388
65389/**
65390 * Helper function to get the items that intersect the event position
65391 * @param {ChartElement[]} items - elements to filter
65392 * @param {object} position - the point to be nearest to
65393 * @return {ChartElement[]} the nearest items
65394 */
65395function getIntersectItems(chart, position) {
65396	var elements = [];
65397
65398	parseVisibleItems(chart, function(element) {
65399		if (element.inRange(position.x, position.y)) {
65400			elements.push(element);
65401		}
65402	});
65403
65404	return elements;
65405}
65406
65407/**
65408 * Helper function to get the items nearest to the event position considering all visible items in teh chart
65409 * @param {Chart} chart - the chart to look at elements from
65410 * @param {object} position - the point to be nearest to
65411 * @param {boolean} intersect - if true, only consider items that intersect the position
65412 * @param {function} distanceMetric - function to provide the distance between points
65413 * @return {ChartElement[]} the nearest items
65414 */
65415function getNearestItems(chart, position, intersect, distanceMetric) {
65416	var minDistance = Number.POSITIVE_INFINITY;
65417	var nearestItems = [];
65418
65419	parseVisibleItems(chart, function(element) {
65420		if (intersect && !element.inRange(position.x, position.y)) {
65421			return;
65422		}
65423
65424		var center = element.getCenterPoint();
65425		var distance = distanceMetric(position, center);
65426		if (distance < minDistance) {
65427			nearestItems = [element];
65428			minDistance = distance;
65429		} else if (distance === minDistance) {
65430			// Can have multiple items at the same distance in which case we sort by size
65431			nearestItems.push(element);
65432		}
65433	});
65434
65435	return nearestItems;
65436}
65437
65438/**
65439 * Get a distance metric function for two points based on the
65440 * axis mode setting
65441 * @param {string} axis - the axis mode. x|y|xy
65442 */
65443function getDistanceMetricForAxis(axis) {
65444	var useX = axis.indexOf('x') !== -1;
65445	var useY = axis.indexOf('y') !== -1;
65446
65447	return function(pt1, pt2) {
65448		var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
65449		var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
65450		return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
65451	};
65452}
65453
65454function indexMode(chart, e, options) {
65455	var position = getRelativePosition(e, chart);
65456	// Default axis for index mode is 'x' to match old behaviour
65457	options.axis = options.axis || 'x';
65458	var distanceMetric = getDistanceMetricForAxis(options.axis);
65459	var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
65460	var elements = [];
65461
65462	if (!items.length) {
65463		return [];
65464	}
65465
65466	chart.data.datasets.forEach(function(dataset, datasetIndex) {
65467		if (chart.isDatasetVisible(datasetIndex)) {
65468			var meta = chart.getDatasetMeta(datasetIndex);
65469			var element = meta.data[items[0]._index];
65470
65471			// don't count items that are skipped (null data)
65472			if (element && !element._view.skip) {
65473				elements.push(element);
65474			}
65475		}
65476	});
65477
65478	return elements;
65479}
65480
65481/**
65482 * @interface IInteractionOptions
65483 */
65484/**
65485 * If true, only consider items that intersect the point
65486 * @name IInterfaceOptions#boolean
65487 * @type Boolean
65488 */
65489
65490/**
65491 * Contains interaction related functions
65492 * @namespace Chart.Interaction
65493 */
65494var core_interaction = {
65495	// Helper function for different modes
65496	modes: {
65497		single: function(chart, e) {
65498			var position = getRelativePosition(e, chart);
65499			var elements = [];
65500
65501			parseVisibleItems(chart, function(element) {
65502				if (element.inRange(position.x, position.y)) {
65503					elements.push(element);
65504					return elements;
65505				}
65506			});
65507
65508			return elements.slice(0, 1);
65509		},
65510
65511		/**
65512		 * @function Chart.Interaction.modes.label
65513		 * @deprecated since version 2.4.0
65514		 * @todo remove at version 3
65515		 * @private
65516		 */
65517		label: indexMode,
65518
65519		/**
65520		 * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something
65521		 * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item
65522		 * @function Chart.Interaction.modes.index
65523		 * @since v2.4.0
65524		 * @param {Chart} chart - the chart we are returning items from
65525		 * @param {Event} e - the event we are find things at
65526		 * @param {IInteractionOptions} options - options to use during interaction
65527		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
65528		 */
65529		index: indexMode,
65530
65531		/**
65532		 * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something
65533		 * If the options.intersect is false, we find the nearest item and return the items in that dataset
65534		 * @function Chart.Interaction.modes.dataset
65535		 * @param {Chart} chart - the chart we are returning items from
65536		 * @param {Event} e - the event we are find things at
65537		 * @param {IInteractionOptions} options - options to use during interaction
65538		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
65539		 */
65540		dataset: function(chart, e, options) {
65541			var position = getRelativePosition(e, chart);
65542			options.axis = options.axis || 'xy';
65543			var distanceMetric = getDistanceMetricForAxis(options.axis);
65544			var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
65545
65546			if (items.length > 0) {
65547				items = chart.getDatasetMeta(items[0]._datasetIndex).data;
65548			}
65549
65550			return items;
65551		},
65552
65553		/**
65554		 * @function Chart.Interaction.modes.x-axis
65555		 * @deprecated since version 2.4.0. Use index mode and intersect == true
65556		 * @todo remove at version 3
65557		 * @private
65558		 */
65559		'x-axis': function(chart, e) {
65560			return indexMode(chart, e, {intersect: false});
65561		},
65562
65563		/**
65564		 * Point mode returns all elements that hit test based on the event position
65565		 * of the event
65566		 * @function Chart.Interaction.modes.intersect
65567		 * @param {Chart} chart - the chart we are returning items from
65568		 * @param {Event} e - the event we are find things at
65569		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
65570		 */
65571		point: function(chart, e) {
65572			var position = getRelativePosition(e, chart);
65573			return getIntersectItems(chart, position);
65574		},
65575
65576		/**
65577		 * nearest mode returns the element closest to the point
65578		 * @function Chart.Interaction.modes.intersect
65579		 * @param {Chart} chart - the chart we are returning items from
65580		 * @param {Event} e - the event we are find things at
65581		 * @param {IInteractionOptions} options - options to use
65582		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
65583		 */
65584		nearest: function(chart, e, options) {
65585			var position = getRelativePosition(e, chart);
65586			options.axis = options.axis || 'xy';
65587			var distanceMetric = getDistanceMetricForAxis(options.axis);
65588			return getNearestItems(chart, position, options.intersect, distanceMetric);
65589		},
65590
65591		/**
65592		 * x mode returns the elements that hit-test at the current x coordinate
65593		 * @function Chart.Interaction.modes.x
65594		 * @param {Chart} chart - the chart we are returning items from
65595		 * @param {Event} e - the event we are find things at
65596		 * @param {IInteractionOptions} options - options to use
65597		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
65598		 */
65599		x: function(chart, e, options) {
65600			var position = getRelativePosition(e, chart);
65601			var items = [];
65602			var intersectsItem = false;
65603
65604			parseVisibleItems(chart, function(element) {
65605				if (element.inXRange(position.x)) {
65606					items.push(element);
65607				}
65608
65609				if (element.inRange(position.x, position.y)) {
65610					intersectsItem = true;
65611				}
65612			});
65613
65614			// If we want to trigger on an intersect and we don't have any items
65615			// that intersect the position, return nothing
65616			if (options.intersect && !intersectsItem) {
65617				items = [];
65618			}
65619			return items;
65620		},
65621
65622		/**
65623		 * y mode returns the elements that hit-test at the current y coordinate
65624		 * @function Chart.Interaction.modes.y
65625		 * @param {Chart} chart - the chart we are returning items from
65626		 * @param {Event} e - the event we are find things at
65627		 * @param {IInteractionOptions} options - options to use
65628		 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
65629		 */
65630		y: function(chart, e, options) {
65631			var position = getRelativePosition(e, chart);
65632			var items = [];
65633			var intersectsItem = false;
65634
65635			parseVisibleItems(chart, function(element) {
65636				if (element.inYRange(position.y)) {
65637					items.push(element);
65638				}
65639
65640				if (element.inRange(position.x, position.y)) {
65641					intersectsItem = true;
65642				}
65643			});
65644
65645			// If we want to trigger on an intersect and we don't have any items
65646			// that intersect the position, return nothing
65647			if (options.intersect && !intersectsItem) {
65648				items = [];
65649			}
65650			return items;
65651		}
65652	}
65653};
65654
65655function filterByPosition(array, position) {
65656	return helpers$1.where(array, function(v) {
65657		return v.position === position;
65658	});
65659}
65660
65661function sortByWeight(array, reverse) {
65662	array.forEach(function(v, i) {
65663		v._tmpIndex_ = i;
65664		return v;
65665	});
65666	array.sort(function(a, b) {
65667		var v0 = reverse ? b : a;
65668		var v1 = reverse ? a : b;
65669		return v0.weight === v1.weight ?
65670			v0._tmpIndex_ - v1._tmpIndex_ :
65671			v0.weight - v1.weight;
65672	});
65673	array.forEach(function(v) {
65674		delete v._tmpIndex_;
65675	});
65676}
65677
65678function findMaxPadding(boxes) {
65679	var top = 0;
65680	var left = 0;
65681	var bottom = 0;
65682	var right = 0;
65683	helpers$1.each(boxes, function(box) {
65684		if (box.getPadding) {
65685			var boxPadding = box.getPadding();
65686			top = Math.max(top, boxPadding.top);
65687			left = Math.max(left, boxPadding.left);
65688			bottom = Math.max(bottom, boxPadding.bottom);
65689			right = Math.max(right, boxPadding.right);
65690		}
65691	});
65692	return {
65693		top: top,
65694		left: left,
65695		bottom: bottom,
65696		right: right
65697	};
65698}
65699
65700function addSizeByPosition(boxes, size) {
65701	helpers$1.each(boxes, function(box) {
65702		size[box.position] += box.isHorizontal() ? box.height : box.width;
65703	});
65704}
65705
65706core_defaults._set('global', {
65707	layout: {
65708		padding: {
65709			top: 0,
65710			right: 0,
65711			bottom: 0,
65712			left: 0
65713		}
65714	}
65715});
65716
65717/**
65718 * @interface ILayoutItem
65719 * @prop {string} position - The position of the item in the chart layout. Possible values are
65720 * 'left', 'top', 'right', 'bottom', and 'chartArea'
65721 * @prop {number} weight - The weight used to sort the item. Higher weights are further away from the chart area
65722 * @prop {boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down
65723 * @prop {function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom)
65724 * @prop {function} update - Takes two parameters: width and height. Returns size of item
65725 * @prop {function} getPadding -  Returns an object with padding on the edges
65726 * @prop {number} width - Width of item. Must be valid after update()
65727 * @prop {number} height - Height of item. Must be valid after update()
65728 * @prop {number} left - Left edge of the item. Set by layout system and cannot be used in update
65729 * @prop {number} top - Top edge of the item. Set by layout system and cannot be used in update
65730 * @prop {number} right - Right edge of the item. Set by layout system and cannot be used in update
65731 * @prop {number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update
65732 */
65733
65734// The layout service is very self explanatory.  It's responsible for the layout within a chart.
65735// Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need
65736// It is this service's responsibility of carrying out that layout.
65737var core_layouts = {
65738	defaults: {},
65739
65740	/**
65741	 * Register a box to a chart.
65742	 * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title.
65743	 * @param {Chart} chart - the chart to use
65744	 * @param {ILayoutItem} item - the item to add to be layed out
65745	 */
vendor: 4,697 bytes, lines 65746-65864
65746	addBox: function(chart, item) {
65747		if (!chart.boxes) {
65748			chart.boxes = [];
65749		}
65750
65751		// initialize item with default values
65752		item.fullWidth = item.fullWidth || false;
65753		item.position = item.position || 'top';
65754		item.weight = item.weight || 0;
65755
65756		chart.boxes.push(item);
65757	},
65758
65759	/**
65760	 * Remove a layoutItem from a chart
65761	 * @param {Chart} chart - the chart to remove the box from
65762	 * @param {ILayoutItem} layoutItem - the item to remove from the layout
65763	 */
65764	removeBox: function(chart, layoutItem) {
65765		var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
65766		if (index !== -1) {
65767			chart.boxes.splice(index, 1);
65768		}
65769	},
65770
65771	/**
65772	 * Sets (or updates) options on the given `item`.
65773	 * @param {Chart} chart - the chart in which the item lives (or will be added to)
65774	 * @param {ILayoutItem} item - the item to configure with the given options
65775	 * @param {object} options - the new item options.
65776	 */
65777	configure: function(chart, item, options) {
65778		var props = ['fullWidth', 'position', 'weight'];
65779		var ilen = props.length;
65780		var i = 0;
65781		var prop;
65782
65783		for (; i < ilen; ++i) {
65784			prop = props[i];
65785			if (options.hasOwnProperty(prop)) {
65786				item[prop] = options[prop];
65787			}
65788		}
65789	},
65790
65791	/**
65792	 * Fits boxes of the given chart into the given size by having each box measure itself
65793	 * then running a fitting algorithm
65794	 * @param {Chart} chart - the chart
65795	 * @param {number} width - the width to fit into
65796	 * @param {number} height - the height to fit into
65797	 */
65798	update: function(chart, width, height) {
65799		if (!chart) {
65800			return;
65801		}
65802
65803		var layoutOptions = chart.options.layout || {};
65804		var padding = helpers$1.options.toPadding(layoutOptions.padding);
65805		var leftPadding = padding.left;
65806		var rightPadding = padding.right;
65807		var topPadding = padding.top;
65808		var bottomPadding = padding.bottom;
65809
65810		var leftBoxes = filterByPosition(chart.boxes, 'left');
65811		var rightBoxes = filterByPosition(chart.boxes, 'right');
65812		var topBoxes = filterByPosition(chart.boxes, 'top');
65813		var bottomBoxes = filterByPosition(chart.boxes, 'bottom');
65814		var chartAreaBoxes = filterByPosition(chart.boxes, 'chartArea');
65815
65816		// Sort boxes by weight. A higher weight is further away from the chart area
65817		sortByWeight(leftBoxes, true);
65818		sortByWeight(rightBoxes, false);
65819		sortByWeight(topBoxes, true);
65820		sortByWeight(bottomBoxes, false);
65821
65822		var verticalBoxes = leftBoxes.concat(rightBoxes);
65823		var horizontalBoxes = topBoxes.concat(bottomBoxes);
65824		var outerBoxes = verticalBoxes.concat(horizontalBoxes);
65825
65826		// Essentially we now have any number of boxes on each of the 4 sides.
65827		// Our canvas looks like the following.
65828		// The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
65829		// B1 is the bottom axis
65830		// There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays
65831		// These locations are single-box locations only, when trying to register a chartArea location that is already taken,
65832		// an error will be thrown.
65833		//
65834		// |----------------------------------------------------|
65835		// |                  T1 (Full Width)                   |
65836		// |----------------------------------------------------|
65837		// |    |    |                 T2                  |    |
65838		// |    |----|-------------------------------------|----|
65839		// |    |    | C1 |                           | C2 |    |
65840		// |    |    |----|                           |----|    |
65841		// |    |    |                                     |    |
65842		// | L1 | L2 |           ChartArea (C0)            | R1 |
65843		// |    |    |                                     |    |
65844		// |    |    |----|                           |----|    |
65845		// |    |    | C3 |                           | C4 |    |
65846		// |    |----|-------------------------------------|----|
65847		// |    |    |                 B1                  |    |
65848		// |----------------------------------------------------|
65849		// |                  B2 (Full Width)                   |
65850		// |----------------------------------------------------|
65851		//
65852		// What we do to find the best sizing, we do the following
65853		// 1. Determine the minimum size of the chart area.
65854		// 2. Split the remaining width equally between each vertical axis
65855		// 3. Split the remaining height equally between each horizontal axis
65856		// 4. Give each layout the maximum size it can be. The layout will return it's minimum size
65857		// 5. Adjust the sizes of each axis based on it's minimum reported size.
65858		// 6. Refit each axis
65859		// 7. Position each axis in the final location
65860		// 8. Tell the chart the final location of the chart area
65861		// 9. Tell any axes that overlay the chart area the positions of the chart area
65862
65863		// Step 1
65864		var chartWidth = width - leftPadding - rightPadding;
65865		var chartHeight = height - topPadding - bottomPadding;
65866		var chartAreaWidth = chartWidth / 2; // min 50%
65867
65868		// Step 2
65869		var verticalBoxWidth = (width - chartAreaWidth) / verticalBoxes.length;
65870
65871		// Step 3
65872		// TODO re-limit horizontal axis height (this limit has affected only padding calculation since PR 1837)
65873		// var horizontalBoxHeight = (height - chartAreaHeight) / horizontalBoxes.length;
65874
65875		// Step 4
65876		var maxChartAreaWidth = chartWidth;
65877		var maxChartAreaHeight = chartHeight;
65878		var outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding};
65879		var minBoxSizes = [];
65880		var maxPadding;
65881
65882		function getMinimumBoxSize(box) {
65883			var minSize;
65884			var isHorizontal = box.isHorizontal();
65885
65886			if (isHorizontal) {
65887				minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2);
65888				maxChartAreaHeight -= minSize.height;
65889			} else {
65890				minSize = box.update(verticalBoxWidth, maxChartAreaHeight);
65891				maxChartAreaWidth -= minSize.width;
65892			}
65893
65894			minBoxSizes.push({
65895				horizontal: isHorizontal,
65896				width: minSize.width,
65897				box: box,
65898			});
65899		}
65900
65901		helpers$1.each(outerBoxes, getMinimumBoxSize);
65902
65903		// If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478)
65904		maxPadding = findMaxPadding(outerBoxes);
65905
65906		// At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
65907		// be if the axes are drawn at their minimum sizes.
65908		// Steps 5 & 6
65909
65910		// Function to fit a box
65911		function fitBox(box) {
65912			var minBoxSize = helpers$1.findNextWhere(minBoxSizes, function(minBox) {
65913				return minBox.box === box;
65914			});
65915
65916			if (minBoxSize) {
65917				if (minBoxSize.horizontal) {
65918					var scaleMargin = {
65919						left: Math.max(outerBoxSizes.left, maxPadding.left),
65920						right: Math.max(outerBoxSizes.right, maxPadding.right),
65921						top: 0,
65922						bottom: 0
65923					};
65924
65925					// Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends
65926					// on the margin. Sometimes they need to increase in size slightly
65927					box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
65928				} else {
65929					box.update(minBoxSize.width, maxChartAreaHeight);
65930				}
65931			}
65932		}
65933
65934		// Update, and calculate the left and right margins for the horizontal boxes
65935		helpers$1.each(verticalBoxes, fitBox);
65936		addSizeByPosition(verticalBoxes, outerBoxSizes);
65937
65938		// Set the Left and Right margins for the horizontal boxes
65939		helpers$1.each(horizontalBoxes, fitBox);
65940		addSizeByPosition(horizontalBoxes, outerBoxSizes);
65941
65942		function finalFitVerticalBox(box) {
65943			var minBoxSize = helpers$1.findNextWhere(minBoxSizes, function(minSize) {
65944				return minSize.box === box;
65945			});
65946
65947			var scaleMargin = {
65948				left: 0,
65949				right: 0,
65950				top: outerBoxSizes.top,
65951				bottom: outerBoxSizes.bottom
65952			};
65953
65954			if (minBoxSize) {
65955				box.update(minBoxSize.width, maxChartAreaHeight, scaleMargin);
65956			}
65957		}
65958
65959		// Let the left layout know the final margin
65960		helpers$1.each(verticalBoxes, finalFitVerticalBox);
65961
65962		// Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
65963		outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding};
65964		addSizeByPosition(outerBoxes, outerBoxSizes);
65965
65966		// We may be adding some padding to account for rotated x axis labels
65967		var leftPaddingAddition = Math.max(maxPadding.left - outerBoxSizes.left, 0);
65968		outerBoxSizes.left += leftPaddingAddition;
65969		outerBoxSizes.right += Math.max(maxPadding.right - outerBoxSizes.right, 0);
65970
65971		var topPaddingAddition = Math.max(maxPadding.top - outerBoxSizes.top, 0);
65972		outerBoxSizes.top += topPaddingAddition;
65973		outerBoxSizes.bottom += Math.max(maxPadding.bottom - outerBoxSizes.bottom, 0);
65974
65975		// Figure out if our chart area changed. This would occur if the dataset layout label rotation
65976		// changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
65977		// without calling `fit` again
65978		var newMaxChartAreaHeight = height - outerBoxSizes.top - outerBoxSizes.bottom;
65979		var newMaxChartAreaWidth = width - outerBoxSizes.left - outerBoxSizes.right;
65980
65981		if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
65982			helpers$1.each(verticalBoxes, function(box) {
65983				box.height = newMaxChartAreaHeight;
65984			});
65985
65986			helpers$1.each(horizontalBoxes, function(box) {
65987				if (!box.fullWidth) {
65988					box.width = newMaxChartAreaWidth;
65989				}
65990			});
65991
65992			maxChartAreaHeight = newMaxChartAreaHeight;
65993			maxChartAreaWidth = newMaxChartAreaWidth;
65994		}
65995
65996		// Step 7 - Position the boxes
65997		var left = leftPadding + leftPaddingAddition;
65998		var top = topPadding + topPaddingAddition;
65999
66000		function placeBox(box) {
66001			if (box.isHorizontal()) {
66002				box.left = box.fullWidth ? leftPadding : outerBoxSizes.left;
66003				box.right = box.fullWidth ? width - rightPadding : outerBoxSizes.left + maxChartAreaWidth;
66004				box.top = top;
66005				box.bottom = top + box.height;
66006
66007				// Move to next point
66008				top = box.bottom;
66009
66010			} else {
66011
66012				box.left = left;
66013				box.right = left + box.width;
66014				box.top = outerBoxSizes.top;
66015				box.bottom = outerBoxSizes.top + maxChartAreaHeight;
66016
66017				// Move to next point
66018				left = box.right;
66019			}
66020		}
66021
66022		helpers$1.each(leftBoxes.concat(topBoxes), placeBox);
66023
66024		// Account for chart width and height
66025		left += maxChartAreaWidth;
66026		top += maxChartAreaHeight;
66027
66028		helpers$1.each(rightBoxes, placeBox);
66029		helpers$1.each(bottomBoxes, placeBox);
66030
66031		// Step 8
66032		chart.chartArea = {
66033			left: outerBoxSizes.left,
66034			top: outerBoxSizes.top,
66035			right: outerBoxSizes.left + maxChartAreaWidth,
66036			bottom: outerBoxSizes.top + maxChartAreaHeight
66037		};
66038
66039		// Step 9
66040		helpers$1.each(chartAreaBoxes, function(box) {
66041			box.left = chart.chartArea.left;
66042			box.top = chart.chartArea.top;
66043			box.right = chart.chartArea.right;
66044			box.bottom = chart.chartArea.bottom;
66045
66046			box.update(maxChartAreaWidth, maxChartAreaHeight);
66047		});
66048	}
66049};
66050
66051/**
66052 * Platform fallback implementation (minimal).
66053 * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939
66054 */
66055
66056var platform_basic = {
66057	acquireContext: function(item) {
66058		if (item && item.canvas) {
66059			// Support for any object associated to a canvas (including a context2d)
66060			item = item.canvas;
66061		}
66062
66063		return item && item.getContext('2d') || null;
66064	}
66065};
66066
66067var platform_dom = "/*\n * DOM element rendering detection\n * https://davidwalsh.name/detect-node-insertion\n */\n@keyframes chartjs-render-animation {\n\tfrom { opacity: 0.99; }\n\tto { opacity: 1; }\n}\n\n.chartjs-render-monitor {\n\tanimation: chartjs-render-animation 0.001s;\n}\n\n/*\n * DOM element resizing detection\n * https://github.com/marcj/css-element-queries\n */\n.chartjs-size-monitor,\n.chartjs-size-monitor-expand,\n.chartjs-size-monitor-shrink {\n\tposition: absolute;\n\tdirection: ltr;\n\tleft: 0;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n\tvisibility: hidden;\n\tz-index: -1;\n}\n\n.chartjs-size-monitor-expand > div {\n\tposition: absolute;\n\twidth: 1000000px;\n\theight: 1000000px;\n\tleft: 0;\n\ttop: 0;\n}\n\n.chartjs-size-monitor-shrink > div {\n\tposition: absolute;\n\twidth: 200%;\n\theight: 200%;\n\tleft: 0;\n\ttop: 0;\n}\n";
66068
66069var platform_dom$1 = /*#__PURE__*/Object.freeze({
66070default: platform_dom
66071});
66072
66073var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
66074
66075function commonjsRequire () {
66076	throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
66077}
66078
66079function createCommonjsModule(fn, module) {
66080	return module = { exports: {} }, fn(module, module.exports), module.exports;
66081}
66082
66083function getCjsExportFromNamespace (n) {
66084	return n && n.default || n;
66085}
66086
66087var stylesheet = getCjsExportFromNamespace(platform_dom$1);
66088
66089var EXPANDO_KEY = '$chartjs';
66090var CSS_PREFIX = 'chartjs-';
66091var CSS_SIZE_MONITOR = CSS_PREFIX + 'size-monitor';
66092var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor';
66093var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation';
66094var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart'];
66095
66096/**
66097 * DOM event types -> Chart.js event types.
66098 * Note: only events with different types are mapped.
66099 * @see https://developer.mozilla.org/en-US/docs/Web/Events
66100 */
66101var EVENT_TYPES = {
66102	touchstart: 'mousedown',
66103	touchmove: 'mousemove',
66104	touchend: 'mouseup',
66105	pointerenter: 'mouseenter',
66106	pointerdown: 'mousedown',
66107	pointermove: 'mousemove',
66108	pointerup: 'mouseup',
66109	pointerleave: 'mouseout',
66110	pointerout: 'mouseout'
66111};
66112
66113/**
66114 * The "used" size is the final value of a dimension property after all calculations have
66115 * been performed. This method uses the computed style of `element` but returns undefined
66116 * if the computed style is not expressed in pixels. That can happen in some cases where
66117 * `element` has a size relative to its parent and this last one is not yet displayed,
66118 * for example because of `display: none` on a parent node.
66119 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
66120 * @returns {number} Size in pixels or undefined if unknown.
66121 */
66122function readUsedSize(element, property) {
66123	var value = helpers$1.getStyle(element, property);
66124	var matches = value && value.match(/^(\d+)(\.\d+)?px$/);
66125	return matches ? Number(matches[1]) : undefined;
66126}
66127
66128/**
66129 * Initializes the canvas style and render size without modifying the canvas display size,
66130 * since responsiveness is handled by the controller.resize() method. The config is used
66131 * to determine the aspect ratio to apply in case no explicit height has been specified.
66132 */
66133function initCanvas(canvas, config) {
66134	var style = canvas.style;
66135
66136	// NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it
66137	// returns null or '' if no explicit value has been set to the canvas attribute.
66138	var renderHeight = canvas.getAttribute('height');
66139	var renderWidth = canvas.getAttribute('width');
66140
66141	// Chart.js modifies some canvas values that we want to restore on de
vendor: 99,514 bytes, lines 66141-69677
66141stroy
66142	canvas[EXPANDO_KEY] = {
66143		initial: {
66144			height: renderHeight,
66145			width: renderWidth,
66146			style: {
66147				display: style.display,
66148				height: style.height,
66149				width: style.width
66150			}
66151		}
66152	};
66153
66154	// Force canvas to display as block to avoid extra space caused by inline
66155	// elements, which would interfere with the responsive resize process.
66156	// https://github.com/chartjs/Chart.js/issues/2538
66157	style.display = style.display || 'block';
66158
66159	if (renderWidth === null || renderWidth === '') {
66160		var displayWidth = readUsedSize(canvas, 'width');
66161		if (displayWidth !== undefined) {
66162			canvas.width = displayWidth;
66163		}
66164	}
66165
66166	if (renderHeight === null || renderHeight === '') {
66167		if (canvas.style.height === '') {
66168			// If no explicit render height and style height, let's apply the aspect ratio,
66169			// which one can be specified by the user but also by charts as default option
66170			// (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2.
66171			canvas.height = canvas.width / (config.options.aspectRatio || 2);
66172		} else {
66173			var displayHeight = readUsedSize(canvas, 'height');
66174			if (displayWidth !== undefined) {
66175				canvas.height = displayHeight;
66176			}
66177		}
66178	}
66179
66180	return canvas;
66181}
66182
66183/**
66184 * Detects support for options object argument in addEventListener.
66185 * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
66186 * @private
66187 */
66188var supportsEventListenerOptions = (function() {
66189	var supports = false;
66190	try {
66191		var options = Object.defineProperty({}, 'passive', {
66192			// eslint-disable-next-line getter-return
66193			get: function() {
66194				supports = true;
66195			}
66196		});
66197		window.addEventListener('e', null, options);
66198	} catch (e) {
66199		// continue regardless of error
66200	}
66201	return supports;
66202}());
66203
66204// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
66205// https://github.com/chartjs/Chart.js/issues/4287
66206var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false;
66207
66208function addListener(node, type, listener) {
66209	node.addEventListener(type, listener, eventListenerOptions);
66210}
66211
66212function removeListener(node, type, listener) {
66213	node.removeEventListener(type, listener, eventListenerOptions);
66214}
66215
66216function createEvent(type, chart, x, y, nativeEvent) {
66217	return {
66218		type: type,
66219		chart: chart,
66220		native: nativeEvent || null,
66221		x: x !== undefined ? x : null,
66222		y: y !== undefined ? y : null,
66223	};
66224}
66225
66226function fromNativeEvent(event, chart) {
66227	var type = EVENT_TYPES[event.type] || event.type;
66228	var pos = helpers$1.getRelativePosition(event, chart);
66229	return createEvent(type, chart, pos.x, pos.y, event);
66230}
66231
66232function throttled(fn, thisArg) {
66233	var ticking = false;
66234	var args = [];
66235
66236	return function() {
66237		args = Array.prototype.slice.call(arguments);
66238		thisArg = thisArg || this;
66239
66240		if (!ticking) {
66241			ticking = true;
66242			helpers$1.requestAnimFrame.call(window, function() {
66243				ticking = false;
66244				fn.apply(thisArg, args);
66245			});
66246		}
66247	};
66248}
66249
66250function createDiv(cls) {
66251	var el = document.createElement('div');
66252	el.className = cls || '';
66253	return el;
66254}
66255
66256// Implementation based on https://github.com/marcj/css-element-queries
66257function createResizer(handler) {
66258	var maxSize = 1000000;
66259
66260	// NOTE(SB) Don't use innerHTML because it could be considered unsafe.
66261	// https://github.com/chartjs/Chart.js/issues/5902
66262	var resizer = createDiv(CSS_SIZE_MONITOR);
66263	var expand = createDiv(CSS_SIZE_MONITOR + '-expand');
66264	var shrink = createDiv(CSS_SIZE_MONITOR + '-shrink');
66265
66266	expand.appendChild(createDiv());
66267	shrink.appendChild(createDiv());
66268
66269	resizer.appendChild(expand);
66270	resizer.appendChild(shrink);
66271	resizer._reset = function() {
66272		expand.scrollLeft = maxSize;
66273		expand.scrollTop = maxSize;
66274		shrink.scrollLeft = maxSize;
66275		shrink.scrollTop = maxSize;
66276	};
66277
66278	var onScroll = function() {
66279		resizer._reset();
66280		handler();
66281	};
66282
66283	addListener(expand, 'scroll', onScroll.bind(expand, 'expand'));
66284	addListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink'));
66285
66286	return resizer;
66287}
66288
66289// https://davidwalsh.name/detect-node-insertion
66290function watchForRender(node, handler) {
66291	var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});
66292	var proxy = expando.renderProxy = function(e) {
66293		if (e.animationName === CSS_RENDER_ANIMATION) {
66294			handler();
66295		}
66296	};
66297
66298	helpers$1.each(ANIMATION_START_EVENTS, function(type) {
66299		addListener(node, type, proxy);
66300	});
66301
66302	// #4737: Chrome might skip the CSS animation when the CSS_RENDER_MONITOR class
66303	// is removed then added back immediately (same animation frame?). Accessing the
66304	// `offsetParent` property will force a reflow and re-evaluate the CSS animation.
66305	// https://gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics
66306	// https://github.com/chartjs/Chart.js/issues/4737
66307	expando.reflow = !!node.offsetParent;
66308
66309	node.classList.add(CSS_RENDER_MONITOR);
66310}
66311
66312function unwatchForRender(node) {
66313	var expando = node[EXPANDO_KEY] || {};
66314	var proxy = expando.renderProxy;
66315
66316	if (proxy) {
66317		helpers$1.each(ANIMATION_START_EVENTS, function(type) {
66318			removeListener(node, type, proxy);
66319		});
66320
66321		delete expando.renderProxy;
66322	}
66323
66324	node.classList.remove(CSS_RENDER_MONITOR);
66325}
66326
66327function addResizeListener(node, listener, chart) {
66328	var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});
66329
66330	// Let's keep track of this added resizer and thus avoid DOM query when removing it.
66331	var resizer = expando.resizer = createResizer(throttled(function() {
66332		if (expando.resizer) {
66333			var container = chart.options.maintainAspectRatio && node.parentNode;
66334			var w = container ? container.clientWidth : 0;
66335			listener(createEvent('resize', chart));
66336			if (container && container.clientWidth < w && chart.canvas) {
66337				// If the container size shrank during chart resize, let's assume
66338				// scrollbar appeared. So we resize again with the scrollbar visible -
66339				// effectively making chart smaller and the scrollbar hidden again.
66340				// Because we are inside `throttled`, and currently `ticking`, scroll
66341				// events are ignored during this whole 2 resize process.
66342				// If we assumed wrong and something else happened, we are resizing
66343				// twice in a frame (potential performance issue)
66344				listener(createEvent('resize', chart));
66345			}
66346		}
66347	}));
66348
66349	// The resizer needs to be attached to the node parent, so we first need to be
66350	// sure that `node` is attached to the DOM before injecting the resizer element.
66351	watchForRender(node, function() {
66352		if (expando.resizer) {
66353			var container = node.parentNode;
66354			if (container && container !== resizer.parentNode) {
66355				container.insertBefore(resizer, container.firstChild);
66356			}
66357
66358			// The container size might have changed, let's reset the resizer state.
66359			resizer._reset();
66360		}
66361	});
66362}
66363
66364function removeResizeListener(node) {
66365	var expando = node[EXPANDO_KEY] || {};
66366	var resizer = expando.resizer;
66367
66368	delete expando.resizer;
66369	unwatchForRender(node);
66370
66371	if (resizer && resizer.parentNode) {
66372		resizer.parentNode.removeChild(resizer);
66373	}
66374}
66375
66376function injectCSS(platform, css) {
66377	// https://stackoverflow.com/q/3922139
66378	var style = platform._style || document.createElement('style');
66379	if (!platform._style) {
66380		platform._style = style;
66381		css = '/* Chart.js */\n' + css;
66382		style.setAttribute('type', 'text/css');
66383		document.getElementsByTagName('head')[0].appendChild(style);
66384	}
66385
66386	style.appendChild(document.createTextNode(css));
66387}
66388
66389var platform_dom$2 = {
66390	/**
66391	 * When `true`, prevents the automatic injection of the stylesheet required to
66392	 * correctly detect when the chart is added to the DOM and then resized. This
66393	 * switch has been added to allow external stylesheet (`dist/Chart(.min)?.js`)
66394	 * to be manually imported to make this library compatible with any CSP.
66395	 * See https://github.com/chartjs/Chart.js/issues/5208
66396	 */
66397	disableCSSInjection: false,
66398
66399	/**
66400	 * This property holds whether this platform is enabled for the current environment.
66401	 * Currently used by platform.js to select the proper implementation.
66402	 * @private
66403	 */
66404	_enabled: typeof window !== 'undefined' && typeof document !== 'undefined',
66405
66406	/**
66407	 * @private
66408	 */
66409	_ensureLoaded: function() {
66410		if (this._loaded) {
66411			return;
66412		}
66413
66414		this._loaded = true;
66415
66416		// https://github.com/chartjs/Chart.js/issues/5208
66417		if (!this.disableCSSInjection) {
66418			injectCSS(this, stylesheet);
66419		}
66420	},
66421
66422	acquireContext: function(item, config) {
66423		if (typeof item === 'string') {
66424			item = document.getElementById(item);
66425		} else if (item.length) {
66426			// Support for array based queries (such as jQuery)
66427			item = item[0];
66428		}
66429
66430		if (item && item.canvas) {
66431			// Support for any object associated to a canvas (including a context2d)
66432			item = item.canvas;
66433		}
66434
66435		// To prevent canvas fingerprinting, some add-ons undefine the getContext
66436		// method, for example: https://github.com/kkapsner/CanvasBlocker
66437		// https://github.com/chartjs/Chart.js/issues/2807
66438		var context = item && item.getContext && item.getContext('2d');
66439
66440		// Load platform resources on first chart creation, to make possible to change
66441		// platform options after importing the library (e.g. `disableCSSInjection`).
66442		this._ensureLoaded();
66443
66444		// `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is
66445		// inside an iframe or when running in a protected environment. We could guess the
66446		// types from their toString() value but let's keep things flexible and assume it's
66447		// a sufficient condition if the item has a context2D which has item as `canvas`.
66448		// https://github.com/chartjs/Chart.js/issues/3887
66449		// https://github.com/chartjs/Chart.js/issues/4102
66450		// https://github.com/chartjs/Chart.js/issues/4152
66451		if (context && context.canvas === item) {
66452			initCanvas(item, config);
66453			return context;
66454		}
66455
66456		return null;
66457	},
66458
66459	releaseContext: function(context) {
66460		var canvas = context.canvas;
66461		if (!canvas[EXPANDO_KEY]) {
66462			return;
66463		}
66464
66465		var initial = canvas[EXPANDO_KEY].initial;
66466		['height', 'width'].forEach(function(prop) {
66467			var value = initial[prop];
66468			if (helpers$1.isNullOrUndef(value)) {
66469				canvas.removeAttribute(prop);
66470			} else {
66471				canvas.setAttribute(prop, value);
66472			}
66473		});
66474
66475		helpers$1.each(initial.style || {}, function(value, key) {
66476			canvas.style[key] = value;
66477		});
66478
66479		// The canvas render size might have been changed (and thus the state stack discarded),
66480		// we can't use save() and restore() to restore the initial state. So make sure that at
66481		// least the canvas context is reset to the default state by setting the canvas width.
66482		// https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html
66483		// eslint-disable-next-line no-self-assign
66484		canvas.width = canvas.width;
66485
66486		delete canvas[EXPANDO_KEY];
66487	},
66488
66489	addEventListener: function(chart, type, listener) {
66490		var canvas = chart.canvas;
66491		if (type === 'resize') {
66492			// Note: the resize event is not supported on all browsers.
66493			addResizeListener(canvas, listener, chart);
66494			return;
66495		}
66496
66497		var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {});
66498		var proxies = expando.proxies || (expando.proxies = {});
66499		var proxy = proxies[chart.id + '_' + type] = function(event) {
66500			listener(fromNativeEvent(event, chart));
66501		};
66502
66503		addListener(canvas, type, proxy);
66504	},
66505
66506	removeEventListener: function(chart, type, listener) {
66507		var canvas = chart.canvas;
66508		if (type === 'resize') {
66509			// Note: the resize event is not supported on all browsers.
66510			removeResizeListener(canvas);
66511			return;
66512		}
66513
66514		var expando = listener[EXPANDO_KEY] || {};
66515		var proxies = expando.proxies || {};
66516		var proxy = proxies[chart.id + '_' + type];
66517		if (!proxy) {
66518			return;
66519		}
66520
66521		removeListener(canvas, type, proxy);
66522	}
66523};
66524
66525// DEPRECATIONS
66526
66527/**
66528 * Provided for backward compatibility, use EventTarget.addEventListener instead.
66529 * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
66530 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
66531 * @function Chart.helpers.addEvent
66532 * @deprecated since version 2.7.0
66533 * @todo remove at version 3
66534 * @private
66535 */
66536helpers$1.addEvent = addListener;
66537
66538/**
66539 * Provided for backward compatibility, use EventTarget.removeEventListener instead.
66540 * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+
66541 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
66542 * @function Chart.helpers.removeEvent
66543 * @deprecated since version 2.7.0
66544 * @todo remove at version 3
66545 * @private
66546 */
66547helpers$1.removeEvent = removeListener;
66548
66549// @TODO Make possible to select another platform at build time.
66550var implementation = platform_dom$2._enabled ? platform_dom$2 : platform_basic;
66551
66552/**
66553 * @namespace Chart.platform
66554 * @see https://chartjs.gitbooks.io/proposals/content/Platform.html
66555 * @since 2.4.0
66556 */
66557var platform = helpers$1.extend({
66558	/**
66559	 * @since 2.7.0
66560	 */
66561	initialize: function() {},
66562
66563	/**
66564	 * Called at chart construction time, returns a context2d instance implementing
66565	 * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}.
66566	 * @param {*} item - The native item from which to acquire context (platform specific)
66567	 * @param {object} options - The chart options
66568	 * @returns {CanvasRenderingContext2D} context2d instance
66569	 */
66570	acquireContext: function() {},
66571
66572	/**
66573	 * Called at chart destruction time, releases any resources associated to the context
66574	 * previously returned by the acquireContext() method.
66575	 * @param {CanvasRenderingContext2D} context - The context2d instance
66576	 * @returns {boolean} true if the method succeeded, else false
66577	 */
66578	releaseContext: function() {},
66579
66580	/**
66581	 * Registers the specified listener on the given chart.
66582	 * @param {Chart} chart - Chart from which to listen for event
66583	 * @param {string} type - The ({@link IEvent}) type to listen for
66584	 * @param {function} listener - Receives a notification (an object that implements
66585	 * the {@link IEvent} interface) when an event of the specified type occurs.
66586	 */
66587	addEventListener: function() {},
66588
66589	/**
66590	 * Removes the specified listener previously registered with addEventListener.
66591	 * @param {Chart} chart - Chart from which to remove the listener
66592	 * @param {string} type - The ({@link IEvent}) type to remove
66593	 * @param {function} listener - The listener function to remove from the event target.
66594	 */
66595	removeEventListener: function() {}
66596
66597}, implementation);
66598
66599core_defaults._set('global', {
66600	plugins: {}
66601});
66602
66603/**
66604 * The plugin service singleton
66605 * @namespace Chart.plugins
66606 * @since 2.1.0
66607 */
66608var core_plugins = {
66609	/**
66610	 * Globally registered plugins.
66611	 * @private
66612	 */
66613	_plugins: [],
66614
66615	/**
66616	 * This identifier is used to invalidate the descriptors cache attached to each chart
66617	 * when a global plugin is registered or unregistered. In this case, the cache ID is
66618	 * incremented and descriptors are regenerated during following API calls.
66619	 * @private
66620	 */
66621	_cacheId: 0,
66622
66623	/**
66624	 * Registers the given plugin(s) if not already registered.
66625	 * @param {IPlugin[]|IPlugin} plugins plugin instance(s).
66626	 */
66627	register: function(plugins) {
66628		var p = this._plugins;
66629		([]).concat(plugins).forEach(function(plugin) {
66630			if (p.indexOf(plugin) === -1) {
66631				p.push(plugin);
66632			}
66633		});
66634
66635		this._cacheId++;
66636	},
66637
66638	/**
66639	 * Unregisters the given plugin(s) only if registered.
66640	 * @param {IPlugin[]|IPlugin} plugins plugin instance(s).
66641	 */
66642	unregister: function(plugins) {
66643		var p = this._plugins;
66644		([]).concat(plugins).forEach(function(plugin) {
66645			var idx = p.indexOf(plugin);
66646			if (idx !== -1) {
66647				p.splice(idx, 1);
66648			}
66649		});
66650
66651		this._cacheId++;
66652	},
66653
66654	/**
66655	 * Remove all registered plugins.
66656	 * @since 2.1.5
66657	 */
66658	clear: function() {
66659		this._plugins = [];
66660		this._cacheId++;
66661	},
66662
66663	/**
66664	 * Returns the number of registered plugins?
66665	 * @returns {number}
66666	 * @since 2.1.5
66667	 */
66668	count: function() {
66669		return this._plugins.length;
66670	},
66671
66672	/**
66673	 * Returns all registered plugin instances.
66674	 * @returns {IPlugin[]} array of plugin objects.
66675	 * @since 2.1.5
66676	 */
66677	getAll: function() {
66678		return this._plugins;
66679	},
66680
66681	/**
66682	 * Calls enabled plugins for `chart` on the specified hook and with the given args.
66683	 * This method immediately returns as soon as a plugin explicitly returns false. The
66684	 * returned value can be used, for instance, to interrupt the current action.
66685	 * @param {Chart} chart - The chart instance for which plugins should be called.
66686	 * @param {string} hook - The name of the plugin method to call (e.g. 'beforeUpdate').
66687	 * @param {Array} [args] - Extra arguments to apply to the hook call.
66688	 * @returns {boolean} false if any of the plugins return false, else returns true.
66689	 */
66690	notify: function(chart, hook, args) {
66691		var descriptors = this.descriptors(chart);
66692		var ilen = descriptors.length;
66693		var i, descriptor, plugin, params, method;
66694
66695		for (i = 0; i < ilen; ++i) {
66696			descriptor = descriptors[i];
66697			plugin = descriptor.plugin;
66698			method = plugin[hook];
66699			if (typeof method === 'function') {
66700				params = [chart].concat(args || []);
66701				params.push(descriptor.options);
66702				if (method.apply(plugin, params) === false) {
66703					return false;
66704				}
66705			}
66706		}
66707
66708		return true;
66709	},
66710
66711	/**
66712	 * Returns descriptors of enabled plugins for the given chart.
66713	 * @returns {object[]} [{ plugin, options }]
66714	 * @private
66715	 */
66716	descriptors: function(chart) {
66717		var cache = chart.$plugins || (chart.$plugins = {});
66718		if (cache.id === this._cacheId) {
66719			return cache.descriptors;
66720		}
66721
66722		var plugins = [];
66723		var descriptors = [];
66724		var config = (chart && chart.config) || {};
66725		var options = (config.options && config.options.plugins) || {};
66726
66727		this._plugins.concat(config.plugins || []).forEach(function(plugin) {
66728			var idx = plugins.indexOf(plugin);
66729			if (idx !== -1) {
66730				return;
66731			}
66732
66733			var id = plugin.id;
66734			var opts = options[id];
66735			if (opts === false) {
66736				return;
66737			}
66738
66739			if (opts === true) {
66740				opts = helpers$1.clone(core_defaults.global.plugins[id]);
66741			}
66742
66743			plugins.push(plugin);
66744			descriptors.push({
66745				plugin: plugin,
66746				options: opts || {}
66747			});
66748		});
66749
66750		cache.descriptors = descriptors;
66751		cache.id = this._cacheId;
66752		return descriptors;
66753	},
66754
66755	/**
66756	 * Invalidates cache for the given chart: descriptors hold a reference on plugin option,
66757	 * but in some cases, this reference can be changed by the user when updating options.
66758	 * https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167
66759	 * @private
66760	 */
66761	_invalidate: function(chart) {
66762		delete chart.$plugins;
66763	}
66764};
66765
66766var core_scaleService = {
66767	// Scale registration object. Extensions can register new scale types (such as log or DB scales) and then
66768	// use the new chart options to grab the correct scale
66769	constructors: {},
66770	// Use a registration function so that we can move to an ES6 map when we no longer need to support
66771	// old browsers
66772
66773	// Scale config defaults
66774	defaults: {},
66775	registerScaleType: function(type, scaleConstructor, scaleDefaults) {
66776		this.constructors[type] = scaleConstructor;
66777		this.defaults[type] = helpers$1.clone(scaleDefaults);
66778	},
66779	getScaleConstructor: function(type) {
66780		return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
66781	},
66782	getScaleDefaults: function(type) {
66783		// Return the scale defaults merged with the global settings so that we always use the latest ones
66784		return this.defaults.hasOwnProperty(type) ? helpers$1.merge({}, [core_defaults.scale, this.defaults[type]]) : {};
66785	},
66786	updateScaleDefaults: function(type, additions) {
66787		var me = this;
66788		if (me.defaults.hasOwnProperty(type)) {
66789			me.defaults[type] = helpers$1.extend(me.defaults[type], additions);
66790		}
66791	},
66792	addScalesToLayout: function(chart) {
66793		// Adds each scale to the chart.boxes array to be sized accordingly
66794		helpers$1.each(chart.scales, function(scale) {
66795			// Set ILayoutItem parameters for backwards compatibility
66796			scale.fullWidth = scale.options.fullWidth;
66797			scale.position = scale.options.position;
66798			scale.weight = scale.options.weight;
66799			core_layouts.addBox(chart, scale);
66800		});
66801	}
66802};
66803
66804var valueOrDefault$7 = helpers$1.valueOrDefault;
66805
66806core_defaults._set('global', {
66807	tooltips: {
66808		enabled: true,
66809		custom: null,
66810		mode: 'nearest',
66811		position: 'average',
66812		intersect: true,
66813		backgroundColor: 'rgba(0,0,0,0.8)',
66814		titleFontStyle: 'bold',
66815		titleSpacing: 2,
66816		titleMarginBottom: 6,
66817		titleFontColor: '#fff',
66818		titleAlign: 'left',
66819		bodySpacing: 2,
66820		bodyFontColor: '#fff',
66821		bodyAlign: 'left',
66822		footerFontStyle: 'bold',
66823		footerSpacing: 2,
66824		footerMarginTop: 6,
66825		footerFontColor: '#fff',
66826		footerAlign: 'left',
66827		yPadding: 6,
66828		xPadding: 6,
66829		caretPadding: 2,
66830		caretSize: 5,
66831		cornerRadius: 6,
66832		multiKeyBackground: '#fff',
66833		displayColors: true,
66834		borderColor: 'rgba(0,0,0,0)',
66835		borderWidth: 0,
66836		callbacks: {
66837			// Args are: (tooltipItems, data)
66838			beforeTitle: helpers$1.noop,
66839			title: function(tooltipItems, data) {
66840				var title = '';
66841				var labels = data.labels;
66842				var labelCount = labels ? labels.length : 0;
66843
66844				if (tooltipItems.length > 0) {
66845					var item = tooltipItems[0];
66846					if (item.label) {
66847						title = item.label;
66848					} else if (item.xLabel) {
66849						title = item.xLabel;
66850					} else if (labelCount > 0 && item.index < labelCount) {
66851						title = labels[item.index];
66852					}
66853				}
66854
66855				return title;
66856			},
66857			afterTitle: helpers$1.noop,
66858
66859			// Args are: (tooltipItems, data)
66860			beforeBody: helpers$1.noop,
66861
66862			// Args are: (tooltipItem, data)
66863			beforeLabel: helpers$1.noop,
66864			label: function(tooltipItem, data) {
66865				var label = data.datasets[tooltipItem.datasetIndex].label || '';
66866
66867				if (label) {
66868					label += ': ';
66869				}
66870				if (!helpers$1.isNullOrUndef(tooltipItem.value)) {
66871					label += tooltipItem.value;
66872				} else {
66873					label += tooltipItem.yLabel;
66874				}
66875				return label;
66876			},
66877			labelColor: function(tooltipItem, chart) {
66878				var meta = chart.getDatasetMeta(tooltipItem.datasetIndex);
66879				var activeElement = meta.data[tooltipItem.index];
66880				var view = activeElement._view;
66881				return {
66882					borderColor: view.borderColor,
66883					backgroundColor: view.backgroundColor
66884				};
66885			},
66886			labelTextColor: function() {
66887				return this._options.bodyFontColor;
66888			},
66889			afterLabel: helpers$1.noop,
66890
66891			// Args are: (tooltipItems, data)
66892			afterBody: helpers$1.noop,
66893
66894			// Args are: (tooltipItems, data)
66895			beforeFooter: helpers$1.noop,
66896			footer: helpers$1.noop,
66897			afterFooter: helpers$1.noop
66898		}
66899	}
66900});
66901
66902var positioners = {
66903	/**
66904	 * Average mode places the tooltip at the average position of the elements shown
66905	 * @function Chart.Tooltip.positioners.average
66906	 * @param elements {ChartElement[]} the elements being displayed in the tooltip
66907	 * @returns {object} tooltip position
66908	 */
66909	average: function(elements) {
66910		if (!elements.length) {
66911			return false;
66912		}
66913
66914		var i, len;
66915		var x = 0;
66916		var y = 0;
66917		var count = 0;
66918
66919		for (i = 0, len = elements.length; i < len; ++i) {
66920			var el = elements[i];
66921			if (el && el.hasValue()) {
66922				var pos = el.tooltipPosition();
66923				x += pos.x;
66924				y += pos.y;
66925				++count;
66926			}
66927		}
66928
66929		return {
66930			x: x / count,
66931			y: y / count
66932		};
66933	},
66934
66935	/**
66936	 * Gets the tooltip position nearest of the item nearest to the event position
66937	 * @function Chart.Tooltip.positioners.nearest
66938	 * @param elements {Chart.Element[]} the tooltip elements
66939	 * @param eventPosition {object} the position of the event in canvas coordinates
66940	 * @returns {object} the tooltip position
66941	 */
66942	nearest: function(elements, eventPosition) {
66943		var x = eventPosition.x;
66944		var y = eventPosition.y;
66945		var minDistance = Number.POSITIVE_INFINITY;
66946		var i, len, nearestElement;
66947
66948		for (i = 0, len = elements.length; i < len; ++i) {
66949			var el = elements[i];
66950			if (el && el.hasValue()) {
66951				var center = el.getCenterPoint();
66952				var d = helpers$1.distanceBetweenPoints(eventPosition, center);
66953
66954				if (d < minDistance) {
66955					minDistance = d;
66956					nearestElement = el;
66957				}
66958			}
66959		}
66960
66961		if (nearestElement) {
66962			var tp = nearestElement.tooltipPosition();
66963			x = tp.x;
66964			y = tp.y;
66965		}
66966
66967		return {
66968			x: x,
66969			y: y
66970		};
66971	}
66972};
66973
66974// Helper to push or concat based on if the 2nd parameter is an array or not
66975function pushOrConcat(base, toPush) {
66976	if (toPush) {
66977		if (helpers$1.isArray(toPush)) {
66978			// base = base.concat(toPush);
66979			Array.prototype.push.apply(base, toPush);
66980		} else {
66981			base.push(toPush);
66982		}
66983	}
66984
66985	return base;
66986}
66987
66988/**
66989 * Returns array of strings split by newline
66990 * @param {string} value - The value to split by newline.
66991 * @returns {string[]} value if newline present - Returned from String split() method
66992 * @function
66993 */
66994function splitNewlines(str) {
66995	if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) {
66996		return str.split('\n');
66997	}
66998	return str;
66999}
67000
67001
67002/**
67003 * Private helper to create a tooltip item model
67004 * @param element - the chart element (point, arc, bar) to create the tooltip item for
67005 * @return new tooltip item
67006 */
67007function createTooltipItem(element) {
67008	var xScale = element._xScale;
67009	var yScale = element._yScale || element._scale; // handle radar || polarArea charts
67010	var index = element._index;
67011	var datasetIndex = element._datasetIndex;
67012	var controller = element._chart.getDatasetMeta(datasetIndex).controller;
67013	var indexScale = controller._getIndexScale();
67014	var valueScale = controller._getValueScale();
67015
67016	return {
67017		xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '',
67018		yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '',
67019		label: indexScale ? '' + indexScale.getLabelForIndex(index, datasetIndex) : '',
67020		value: valueScale ? '' + valueScale.getLabelForIndex(index, datasetIndex) : '',
67021		index: index,
67022		datasetIndex: datasetIndex,
67023		x: element._model.x,
67024		y: element._model.y
67025	};
67026}
67027
67028/**
67029 * Helper to get the reset model for the tooltip
67030 * @param tooltipOpts {object} the tooltip options
67031 */
67032function getBaseModel(tooltipOpts) {
67033	var globalDefaults = core_defaults.global;
67034
67035	return {
67036		// Positioning
67037		xPadding: tooltipOpts.xPadding,
67038		yPadding: tooltipOpts.yPadding,
67039		xAlign: tooltipOpts.xAlign,
67040		yAlign: tooltipOpts.yAlign,
67041
67042		// Body
67043		bodyFontColor: tooltipOpts.bodyFontColor,
67044		_bodyFontFamily: valueOrDefault$7(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
67045		_bodyFontStyle: valueOrDefault$7(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
67046		_bodyAlign: tooltipOpts.bodyAlign,
67047		bodyFontSize: valueOrDefault$7(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
67048		bodySpacing: tooltipOpts.bodySpacing,
67049
67050		// Title
67051		titleFontColor: tooltipOpts.titleFontColor,
67052		_titleFontFamily: valueOrDefault$7(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
67053		_titleFontStyle: valueOrDefault$7(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
67054		titleFontSize: valueOrDefault$7(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
67055		_titleAlign: tooltipOpts.titleAlign,
67056		titleSpacing: tooltipOpts.titleSpacing,
67057		titleMarginBottom: tooltipOpts.titleMarginBottom,
67058
67059		// Footer
67060		footerFontColor: tooltipOpts.footerFontColor,
67061		_footerFontFamily: valueOrDefault$7(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
67062		_footerFontStyle: valueOrDefault$7(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
67063		footerFontSize: valueOrDefault$7(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
67064		_footerAlign: tooltipOpts.footerAlign,
67065		footerSpacing: tooltipOpts.footerSpacing,
67066		footerMarginTop: tooltipOpts.footerMarginTop,
67067
67068		// Appearance
67069		caretSize: tooltipOpts.caretSize,
67070		cornerRadius: tooltipOpts.cornerRadius,
67071		backgroundColor: tooltipOpts.backgroundColor,
67072		opacity: 0,
67073		legendColorBackground: tooltipOpts.multiKeyBackground,
67074		displayColors: tooltipOpts.displayColors,
67075		borderColor: tooltipOpts.borderColor,
67076		borderWidth: tooltipOpts.borderWidth
67077	};
67078}
67079
67080/**
67081 * Get the size of the tooltip
67082 */
67083function getTooltipSize(tooltip, model) {
67084	var ctx = tooltip._chart.ctx;
67085
67086	var height = model.yPadding * 2; // Tooltip Padding
67087	var width = 0;
67088
67089	// Count of all lines in the body
67090	var body = model.body;
67091	var combinedBodyLength = body.reduce(function(count, bodyItem) {
67092		return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
67093	}, 0);
67094	combinedBodyLength += model.beforeBody.length + model.afterBody.length;
67095
67096	var titleLineCount = model.title.length;
67097	var footerLineCount = model.footer.length;
67098	var titleFontSize = model.titleFontSize;
67099	var bodyFontSize = model.bodyFontSize;
67100	var footerFontSize = model.footerFontSize;
67101
67102	height += titleLineCount * titleFontSize; // Title Lines
67103	height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing
67104	height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin
67105	height += combinedBodyLength * bodyFontSize; // Body Lines
67106	height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing
67107	height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin
67108	height += footerLineCount * (footerFontSize); // Footer Lines
67109	height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing
67110
67111	// Title width
67112	var widthPadding = 0;
67113	var maxLineWidth = function(line) {
67114		width = Math.max(width, ctx.measureText(line).width + widthPadding);
67115	};
67116
67117	ctx.font = helpers$1.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily);
67118	helpers$1.each(model.title, maxLineWidth);
67119
67120	// Body width
67121	ctx.font = helpers$1.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily);
67122	helpers$1.each(model.beforeBody.concat(model.afterBody), maxLineWidth);
67123
67124	// Body lines may include some extra width due to the color box
67125	widthPadding = model.displayColors ? (bodyFontSize + 2) : 0;
67126	helpers$1.each(body, function(bodyItem) {
67127		helpers$1.each(bodyItem.before, maxLineWidth);
67128		helpers$1.each(bodyItem.lines, maxLineWidth);
67129		helpers$1.each(bodyItem.after, maxLineWidth);
67130	});
67131
67132	// Reset back to 0
67133	widthPadding = 0;
67134
67135	// Footer width
67136	ctx.font = helpers$1.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily);
67137	helpers$1.each(model.footer, maxLineWidth);
67138
67139	// Add padding
67140	width += 2 * model.xPadding;
67141
67142	return {
67143		width: width,
67144		height: height
67145	};
67146}
67147
67148/**
67149 * Helper to get the alignment of a tooltip given the size
67150 */
67151function determineAlignment(tooltip, size) {
67152	var model = tooltip._model;
67153	var chart = tooltip._chart;
67154	var chartArea = tooltip._chart.chartArea;
67155	var xAlign = 'center';
67156	var yAlign = 'center';
67157
67158	if (model.y < size.height) {
67159		yAlign = 'top';
67160	} else if (model.y > (chart.height - size.height)) {
67161		yAlign = 'bottom';
67162	}
67163
67164	var lf, rf; // functions to determine left, right alignment
67165	var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
67166	var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
67167	var midX = (chartArea.left + chartArea.right) / 2;
67168	var midY = (chartArea.top + chartArea.bottom) / 2;
67169
67170	if (yAlign === 'center') {
67171		lf = function(x) {
67172			return x <= midX;
67173		};
67174		rf = function(x) {
67175			return x > midX;
67176		};
67177	} else {
67178		lf = function(x) {
67179			return x <= (size.width / 2);
67180		};
67181		rf = function(x) {
67182			return x >= (chart.width - (size.width / 2));
67183		};
67184	}
67185
67186	olf = function(x) {
67187		return x + size.width + model.caretSize + model.caretPadding > chart.width;
67188	};
67189	orf = function(x) {
67190		return x - size.width - model.caretSize - model.caretPadding < 0;
67191	};
67192	yf = function(y) {
67193		return y <= midY ? 'top' : 'bottom';
67194	};
67195
67196	if (lf(model.x)) {
67197		xAlign = 'left';
67198
67199		// Is tooltip too wide and goes over the right side of the chart.?
67200		if (olf(model.x)) {
67201			xAlign = 'center';
67202			yAlign = yf(model.y);
67203		}
67204	} else if (rf(model.x)) {
67205		xAlign = 'right';
67206
67207		// Is tooltip too wide and goes outside left edge of canvas?
67208		if (orf(model.x)) {
67209			xAlign = 'center';
67210			yAlign = yf(model.y);
67211		}
67212	}
67213
67214	var opts = tooltip._options;
67215	return {
67216		xAlign: opts.xAlign ? opts.xAlign : xAlign,
67217		yAlign: opts.yAlign ? opts.yAlign : yAlign
67218	};
67219}
67220
67221/**
67222 * Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment
67223 */
67224function getBackgroundPoint(vm, size, alignment, chart) {
67225	// Background Position
67226	var x = vm.x;
67227	var y = vm.y;
67228
67229	var caretSize = vm.caretSize;
67230	var caretPadding = vm.caretPadding;
67231	var cornerRadius = vm.cornerRadius;
67232	var xAlign = alignment.xAlign;
67233	var yAlign = alignment.yAlign;
67234	var paddingAndSize = caretSize + caretPadding;
67235	var radiusAndPadding = cornerRadius + caretPadding;
67236
67237	if (xAlign === 'right') {
67238		x -= size.width;
67239	} else if (xAlign === 'center') {
67240		x -= (size.width / 2);
67241		if (x + size.width > chart.width) {
67242			x = chart.width - size.width;
67243		}
67244		if (x < 0) {
67245			x = 0;
67246		}
67247	}
67248
67249	if (yAlign === 'top') {
67250		y += paddingAndSize;
67251	} else if (yAlign === 'bottom') {
67252		y -= size.height + paddingAndSize;
67253	} else {
67254		y -= (size.height / 2);
67255	}
67256
67257	if (yAlign === 'center') {
67258		if (xAlign === 'left') {
67259			x += paddingAndSize;
67260		} else if (xAlign === 'right') {
67261			x -= paddingAndSize;
67262		}
67263	} else if (xAlign === 'left') {
67264		x -= radiusAndPadding;
67265	} else if (xAlign === 'right') {
67266		x += radiusAndPadding;
67267	}
67268
67269	return {
67270		x: x,
67271		y: y
67272	};
67273}
67274
67275function getAlignedX(vm, align) {
67276	return align === 'center'
67277		? vm.x + vm.width / 2
67278		: align === 'right'
67279			? vm.x + vm.width - vm.xPadding
67280			: vm.x + vm.xPadding;
67281}
67282
67283/**
67284 * Helper to build before and after body lines
67285 */
67286function getBeforeAfterBodyLines(callback) {
67287	return pushOrConcat([], splitNewlines(callback));
67288}
67289
67290var exports$3 = core_element.extend({
67291	initialize: function() {
67292		this._model = getBaseModel(this._options);
67293		this._lastActive = [];
67294	},
67295
67296	// Get the title
67297	// Args are: (tooltipItem, data)
67298	getTitle: function() {
67299		var me = this;
67300		var opts = me._options;
67301		var callbacks = opts.callbacks;
67302
67303		var beforeTitle = callbacks.beforeTitle.apply(me, arguments);
67304		var title = callbacks.title.apply(me, arguments);
67305		var afterTitle = callbacks.afterTitle.apply(me, arguments);
67306
67307		var lines = [];
67308		lines = pushOrConcat(lines, splitNewlines(beforeTitle));
67309		lines = pushOrConcat(lines, splitNewlines(title));
67310		lines = pushOrConcat(lines, splitNewlines(afterTitle));
67311
67312		return lines;
67313	},
67314
67315	// Args are: (tooltipItem, data)
67316	getBeforeBody: function() {
67317		return getBeforeAfterBodyLines(this._options.callbacks.beforeBody.apply(this, arguments));
67318	},
67319
67320	// Args are: (tooltipItem, data)
67321	getBody: function(tooltipItems, data) {
67322		var me = this;
67323		var callbacks = me._options.callbacks;
67324		var bodyItems = [];
67325
67326		helpers$1.each(tooltipItems, function(tooltipItem) {
67327			var bodyItem = {
67328				before: [],
67329				lines: [],
67330				after: []
67331			};
67332			pushOrConcat(bodyItem.before, splitNewlines(callbacks.beforeLabel.call(me, tooltipItem, data)));
67333			pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data));
67334			pushOrConcat(bodyItem.after, splitNewlines(callbacks.afterLabel.call(me, tooltipItem, data)));
67335
67336			bodyItems.push(bodyItem);
67337		});
67338
67339		return bodyItems;
67340	},
67341
67342	// Args are: (tooltipItem, data)
67343	getAfterBody: function() {
67344		return getBeforeAfterBodyLines(this._options.callbacks.afterBody.apply(this, arguments));
67345	},
67346
67347	// Get the footer and beforeFooter and afterFooter lines
67348	// Args are: (tooltipItem, data)
67349	getFooter: function() {
67350		var me = this;
67351		var callbacks = me._options.callbacks;
67352
67353		var beforeFooter = callbacks.beforeFooter.apply(me, arguments);
67354		var footer = callbacks.footer.apply(me, arguments);
67355		var afterFooter = callbacks.afterFooter.apply(me, arguments);
67356
67357		var lines = [];
67358		lines = pushOrConcat(lines, splitNewlines(beforeFooter));
67359		lines = pushOrConcat(lines, splitNewlines(footer));
67360		lines = pushOrConcat(lines, splitNewlines(afterFooter));
67361
67362		return lines;
67363	},
67364
67365	update: function(changed) {
67366		var me = this;
67367		var opts = me._options;
67368
67369		// Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition
67370		// that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time
67371		// which breaks any animations.
67372		var existingModel = me._model;
67373		var model = me._model = getBaseModel(opts);
67374		var active = me._active;
67375
67376		var data = me._data;
67377
67378		// In the case where active.length === 0 we need to keep these at existing values for good animations
67379		var alignment = {
67380			xAlign: existingModel.xAlign,
67381			yAlign: existingModel.yAlign
67382		};
67383		var backgroundPoint = {
67384			x: existingModel.x,
67385			y: existingModel.y
67386		};
67387		var tooltipSize = {
67388			width: existingModel.width,
67389			height: existingModel.height
67390		};
67391		var tooltipPosition = {
67392			x: existingModel.caretX,
67393			y: existingModel.caretY
67394		};
67395
67396		var i, len;
67397
67398		if (active.length) {
67399			model.opacity = 1;
67400
67401			var labelColors = [];
67402			var labelTextColors = [];
67403			tooltipPosition = positioners[opts.position].call(me, active, me._eventPosition);
67404
67405			var tooltipItems = [];
67406			for (i = 0, len = active.length; i < len; ++i) {
67407				tooltipItems.push(createTooltipItem(active[i]));
67408			}
67409
67410			// If the user provided a filter function, use it to modify the tooltip items
67411			if (opts.filter) {
67412				tooltipItems = tooltipItems.filter(function(a) {
67413					return opts.filter(a, data);
67414				});
67415			}
67416
67417			// If the user provided a sorting function, use it to modify the tooltip items
67418			if (opts.itemSort) {
67419				tooltipItems = tooltipItems.sort(function(a, b) {
67420					return opts.itemSort(a, b, data);
67421				});
67422			}
67423
67424			// Determine colors for boxes
67425			helpers$1.each(tooltipItems, function(tooltipItem) {
67426				labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, me._chart));
67427				labelTextColors.push(opts.callbacks.labelTextColor.call(me, tooltipItem, me._chart));
67428			});
67429
67430
67431			// Build the Text Lines
67432			model.title = me.getTitle(tooltipItems, data);
67433			model.beforeBody = me.getBeforeBody(tooltipItems, data);
67434			model.body = me.getBody(tooltipItems, data);
67435			model.afterBody = me.getAfterBody(tooltipItems, data);
67436			model.footer = me.getFooter(tooltipItems, data);
67437
67438			// Initial positioning and colors
67439			model.x = tooltipPosition.x;
67440			model.y = tooltipPosition.y;
67441			model.caretPadding = opts.caretPadding;
67442			model.labelColors = labelColors;
67443			model.labelTextColors = labelTextColors;
67444
67445			// data points
67446			model.dataPoints = tooltipItems;
67447
67448			// We need to determine alignment of the tooltip
67449			tooltipSize = getTooltipSize(this, model);
67450			alignment = determineAlignment(this, tooltipSize);
67451			// Final Size and Position
67452			backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment, me._chart);
67453		} else {
67454			model.opacity = 0;
67455		}
67456
67457		model.xAlign = alignment.xAlign;
67458		model.yAlign = alignment.yAlign;
67459		model.x = backgroundPoint.x;
67460		model.y = backgroundPoint.y;
67461		model.width = tooltipSize.width;
67462		model.height = tooltipSize.height;
67463
67464		// Point where the caret on the tooltip points to
67465		model.caretX = tooltipPosition.x;
67466		model.caretY = tooltipPosition.y;
67467
67468		me._model = model;
67469
67470		if (changed && opts.custom) {
67471			opts.custom.call(me, model);
67472		}
67473
67474		return me;
67475	},
67476
67477	drawCaret: function(tooltipPoint, size) {
67478		var ctx = this._chart.ctx;
67479		var vm = this._view;
67480		var caretPosition = this.getCaretPosition(tooltipPoint, size, vm);
67481
67482		ctx.lineTo(caretPosition.x1, caretPosition.y1);
67483		ctx.lineTo(caretPosition.x2, caretPosition.y2);
67484		ctx.lineTo(caretPosition.x3, caretPosition.y3);
67485	},
67486	getCaretPosition: function(tooltipPoint, size, vm) {
67487		var x1, x2, x3, y1, y2, y3;
67488		var caretSize = vm.caretSize;
67489		var cornerRadius = vm.cornerRadius;
67490		var xAlign = vm.xAlign;
67491		var yAlign = vm.yAlign;
67492		var ptX = tooltipPoint.x;
67493		var ptY = tooltipPoint.y;
67494		var width = size.width;
67495		var height = size.height;
67496
67497		if (yAlign === 'center') {
67498			y2 = ptY + (height / 2);
67499
67500			if (xAlign === 'left') {
67501				x1 = ptX;
67502				x2 = x1 - caretSize;
67503				x3 = x1;
67504
67505				y1 = y2 + caretSize;
67506				y3 = y2 - caretSize;
67507			} else {
67508				x1 = ptX + width;
67509				x2 = x1 + caretSize;
67510				x3 = x1;
67511
67512				y1 = y2 - caretSize;
67513				y3 = y2 + caretSize;
67514			}
67515		} else {
67516			if (xAlign === 'left') {
67517				x2 = ptX + cornerRadius + (caretSize);
67518				x1 = x2 - caretSize;
67519				x3 = x2 + caretSize;
67520			} else if (xAlign === 'right') {
67521				x2 = ptX + width - cornerRadius - caretSize;
67522				x1 = x2 - caretSize;
67523				x3 = x2 + caretSize;
67524			} else {
67525				x2 = vm.caretX;
67526				x1 = x2 - caretSize;
67527				x3 = x2 + caretSize;
67528			}
67529			if (yAlign === 'top') {
67530				y1 = ptY;
67531				y2 = y1 - caretSize;
67532				y3 = y1;
67533			} else {
67534				y1 = ptY + height;
67535				y2 = y1 + caretSize;
67536				y3 = y1;
67537				// invert drawing order
67538				var tmp = x3;
67539				x3 = x1;
67540				x1 = tmp;
67541			}
67542		}
67543		return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3};
67544	},
67545
67546	drawTitle: function(pt, vm, ctx) {
67547		var title = vm.title;
67548
67549		if (title.length) {
67550			pt.x = getAlignedX(vm, vm._titleAlign);
67551
67552			ctx.textAlign = vm._titleAlign;
67553			ctx.textBaseline = 'top';
67554
67555			var titleFontSize = vm.titleFontSize;
67556			var titleSpacing = vm.titleSpacing;
67557
67558			ctx.fillStyle = vm.titleFontColor;
67559			ctx.font = helpers$1.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
67560
67561			var i, len;
67562			for (i = 0, len = title.length; i < len; ++i) {
67563				ctx.fillText(title[i], pt.x, pt.y);
67564				pt.y += titleFontSize + titleSpacing; // Line Height and spacing
67565
67566				if (i + 1 === title.length) {
67567					pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
67568				}
67569			}
67570		}
67571	},
67572
67573	drawBody: function(pt, vm, ctx) {
67574		var bodyFontSize = vm.bodyFontSize;
67575		var bodySpacing = vm.bodySpacing;
67576		var bodyAlign = vm._bodyAlign;
67577		var body = vm.body;
67578		var drawColorBoxes = vm.displayColors;
67579		var labelColors = vm.labelColors;
67580		var xLinePadding = 0;
67581		var colorX = drawColorBoxes ? getAlignedX(vm, 'left') : 0;
67582		var textColor;
67583
67584		ctx.textAlign = bodyAlign;
67585		ctx.textBaseline = 'top';
67586		ctx.font = helpers$1.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
67587
67588		pt.x = getAlignedX(vm, bodyAlign);
67589
67590		// Before Body
67591		var fillLineOfText = function(line) {
67592			ctx.fillText(line, pt.x + xLinePadding, pt.y);
67593			pt.y += bodyFontSize + bodySpacing;
67594		};
67595
67596		// Before body lines
67597		ctx.fillStyle = vm.bodyFontColor;
67598		helpers$1.each(vm.beforeBody, fillLineOfText);
67599
67600		xLinePadding = drawColorBoxes && bodyAlign !== 'right'
67601			? bodyAlign === 'center' ? (bodyFontSize / 2 + 1) : (bodyFontSize + 2)
67602			: 0;
67603
67604		// Draw body lines now
67605		helpers$1.each(body, function(bodyItem, i) {
67606			textColor = vm.labelTextColors[i];
67607			ctx.fillStyle = textColor;
67608			helpers$1.each(bodyItem.before, fillLineOfText);
67609
67610			helpers$1.each(bodyItem.lines, function(line) {
67611				// Draw Legend-like boxes if needed
67612				if (drawColorBoxes) {
67613					// Fill a white rect so that colours merge nicely if the opacity is < 1
67614					ctx.fillStyle = vm.legendColorBackground;
67615					ctx.fillRect(colorX, pt.y, bodyFontSize, bodyFontSize);
67616
67617					// Border
67618					ctx.lineWidth = 1;
67619					ctx.strokeStyle = labelColors[i].borderColor;
67620					ctx.strokeRect(colorX, pt.y, bodyFontSize, bodyFontSize);
67621
67622					// Inner square
67623					ctx.fillStyle = labelColors[i].backgroundColor;
67624					ctx.fillRect(colorX + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2);
67625					ctx.fillStyle = textColor;
67626				}
67627
67628				fillLineOfText(line);
67629			});
67630
67631			helpers$1.each(bodyItem.after, fillLineOfText);
67632		});
67633
67634		// Reset back to 0 for after body
67635		xLinePadding = 0;
67636
67637		// After body lines
67638		helpers$1.each(vm.afterBody, fillLineOfText);
67639		pt.y -= bodySpacing; // Remove last body spacing
67640	},
67641
67642	drawFooter: function(pt, vm, ctx) {
67643		var footer = vm.footer;
67644
67645		if (footer.length) {
67646			pt.x = getAlignedX(vm, vm._footerAlign);
67647			pt.y += vm.footerMarginTop;
67648
67649			ctx.textAlign = vm._footerAlign;
67650			ctx.textBaseline = 'top';
67651
67652			ctx.fillStyle = vm.footerFontColor;
67653			ctx.font = helpers$1.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
67654
67655			helpers$1.each(footer, function(line) {
67656				ctx.fillText(line, pt.x, pt.y);
67657				pt.y += vm.footerFontSize + vm.footerSpacing;
67658			});
67659		}
67660	},
67661
67662	drawBackground: function(pt, vm, ctx, tooltipSize) {
67663		ctx.fillStyle = vm.backgroundColor;
67664		ctx.strokeStyle = vm.borderColor;
67665		ctx.lineWidth = vm.borderWidth;
67666		var xAlign = vm.xAlign;
67667		var yAlign = vm.yAlign;
67668		var x = pt.x;
67669		var y = pt.y;
67670		var width = tooltipSize.width;
67671		var height = tooltipSize.height;
67672		var radius = vm.cornerRadius;
67673
67674		ctx.beginPath();
67675		ctx.moveTo(x + radius, y);
67676		if (yAlign === 'top') {
67677			this.drawCaret(pt, tooltipSize);
67678		}
67679		ctx.lineTo(x + width - radius, y);
67680		ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
67681		if (yAlign === 'center' && xAlign === 'right') {
67682			this.drawCaret(pt, tooltipSize);
67683		}
67684		ctx.lineTo(x + width, y + height - radius);
67685		ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
67686		if (yAlign === 'bottom') {
67687			this.drawCaret(pt, tooltipSize);
67688		}
67689		ctx.lineTo(x + radius, y + height);
67690		ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
67691		if (yAlign === 'center' && xAlign === 'left') {
67692			this.drawCaret(pt, tooltipSize);
67693		}
67694		ctx.lineTo(x, y + radius);
67695		ctx.quadraticCurveTo(x, y, x + radius, y);
67696		ctx.closePath();
67697
67698		ctx.fill();
67699
67700		if (vm.borderWidth > 0) {
67701			ctx.stroke();
67702		}
67703	},
67704
67705	draw: function() {
67706		var ctx = this._chart.ctx;
67707		var vm = this._view;
67708
67709		if (vm.opacity === 0) {
67710			return;
67711		}
67712
67713		var tooltipSize = {
67714			width: vm.width,
67715			height: vm.height
67716		};
67717		var pt = {
67718			x: vm.x,
67719			y: vm.y
67720		};
67721
67722		// IE11/Edge does not like very small opacities, so snap to 0
67723		var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
67724
67725		// Truthy/falsey value for empty tooltip
67726		var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length;
67727
67728		if (this._options.enabled && hasTooltipContent) {
67729			ctx.save();
67730			ctx.globalAlpha = opacity;
67731
67732			// Draw Background
67733			this.drawBackground(pt, vm, ctx, tooltipSize);
67734
67735			// Draw Title, Body, and Footer
67736			pt.y += vm.yPadding;
67737
67738			// Titles
67739			this.drawTitle(pt, vm, ctx);
67740
67741			// Body
67742			this.drawBody(pt, vm, ctx);
67743
67744			// Footer
67745			this.drawFooter(pt, vm, ctx);
67746
67747			ctx.restore();
67748		}
67749	},
67750
67751	/**
67752	 * Handle an event
67753	 * @private
67754	 * @param {IEvent} event - The event to handle
67755	 * @returns {boolean} true if the tooltip changed
67756	 */
67757	handleEvent: function(e) {
67758		var me = this;
67759		var options = me._options;
67760		var changed = false;
67761
67762		me._lastActive = me._lastActive || [];
67763
67764		// Find Active Elements for tooltips
67765		if (e.type === 'mouseout') {
67766			me._active = [];
67767		} else {
67768			me._active = me._chart.getElementsAtEventForMode(e, options.mode, options);
67769		}
67770
67771		// Remember Last Actives
67772		changed = !helpers$1.arrayEquals(me._active, me._lastActive);
67773
67774		// Only handle target event on tooltip change
67775		if (changed) {
67776			me._lastActive = me._active;
67777
67778			if (options.enabled || options.custom) {
67779				me._eventPosition = {
67780					x: e.x,
67781					y: e.y
67782				};
67783
67784				me.update(true);
67785				me.pivot();
67786			}
67787		}
67788
67789		return changed;
67790	}
67791});
67792
67793/**
67794 * @namespace Chart.Tooltip.positioners
67795 */
67796var positioners_1 = positioners;
67797
67798var core_tooltip = exports$3;
67799core_tooltip.positioners = positioners_1;
67800
67801var valueOrDefault$8 = helpers$1.valueOrDefault;
67802
67803core_defaults._set('global', {
67804	elements: {},
67805	events: [
67806		'mousemove',
67807		'mouseout',
67808		'click',
67809		'touchstart',
67810		'touchmove'
67811	],
67812	hover: {
67813		onHover: null,
67814		mode: 'nearest',
67815		intersect: true,
67816		animationDuration: 400
67817	},
67818	onClick: null,
67819	maintainAspectRatio: true,
67820	responsive: true,
67821	responsiveAnimationDuration: 0
67822});
67823
67824/**
67825 * Recursively merge the given config objects representing the `scales` option
67826 * by incorporating scale defaults in `xAxes` and `yAxes` array items, then
67827 * returns a deep copy of the result, thus doesn't alter inputs.
67828 */
67829function mergeScaleConfig(/* config objects ... */) {
67830	return helpers$1.merge({}, [].slice.call(arguments), {
67831		merger: function(key, target, source, options) {
67832			if (key === 'xAxes' || key === 'yAxes') {
67833				var slen = source[key].length;
67834				var i, type, scale;
67835
67836				if (!target[key]) {
67837					target[key] = [];
67838				}
67839
67840				for (i = 0; i < slen; ++i) {
67841					scale = source[key][i];
67842					type = valueOrDefault$8(scale.type, key === 'xAxes' ? 'category' : 'linear');
67843
67844					if (i >= target[key].length) {
67845						target[key].push({});
67846					}
67847
67848					if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) {
67849						// new/untyped scale or type changed: let's apply the new defaults
67850						// then merge source scale to correctly overwrite the defaults.
67851						helpers$1.merge(target[key][i], [core_scaleService.getScaleDefaults(type), scale]);
67852					} else {
67853						// scales type are the same
67854						helpers$1.merge(target[key][i], scale);
67855					}
67856				}
67857			} else {
67858				helpers$1._merger(key, target, source, options);
67859			}
67860		}
67861	});
67862}
67863
67864/**
67865 * Recursively merge the given config objects as the root options by handling
67866 * default scale options for the `scales` and `scale` properties, then returns
67867 * a deep copy of the result, thus doesn't alter inputs.
67868 */
67869function mergeConfig(/* config objects ... */) {
67870	return helpers$1.merge({}, [].slice.call(arguments), {
67871		merger: function(key, target, source, options) {
67872			var tval = target[key] || {};
67873			var sval = source[key];
67874
67875			if (key === 'scales') {
67876				// scale config merging is complex. Add our own function here for that
67877				target[key] = mergeScaleConfig(tval, sval);
67878			} else if (key === 'scale') {
67879				// used in polar area & radar charts since there is only one scale
67880				target[key] = helpers$1.merge(tval, [core_scaleService.getScaleDefaults(sval.type), sval]);
67881			} else {
67882				helpers$1._merger(key, target, source, options);
67883			}
67884		}
67885	});
67886}
67887
67888function initConfig(config) {
67889	config = config || {};
67890
67891	// Do NOT use mergeConfig for the data object because this method merges arrays
67892	// and so would change references to labels and datasets, preventing data updates.
67893	var data = config.data = config.data || {};
67894	data.datasets = data.datasets || [];
67895	data.labels = data.labels || [];
67896
67897	config.options = mergeConfig(
67898		core_defaults.global,
67899		core_defaults[config.type],
67900		config.options || {});
67901
67902	return config;
67903}
67904
67905function updateConfig(chart) {
67906	var newOptions = chart.options;
67907
67908	helpers$1.each(chart.scales, function(scale) {
67909		core_layouts.removeBox(chart, scale);
67910	});
67911
67912	newOptions = mergeConfig(
67913		core_defaults.global,
67914		core_defaults[chart.config.type],
67915		newOptions);
67916
67917	chart.options = chart.config.options = newOptions;
67918	chart.ensureScalesHaveIDs();
67919	chart.buildOrUpdateScales();
67920
67921	// Tooltip
67922	chart.tooltip._options = newOptions.tooltips;
67923	chart.tooltip.initialize();
67924}
67925
67926function positionIsHorizontal(position) {
67927	return position === 'top' || position === 'bottom';
67928}
67929
67930var Chart = function(item, config) {
67931	this.construct(item, config);
67932	return this;
67933};
67934
67935helpers$1.extend(Chart.prototype, /** @lends Chart */ {
67936	/**
67937	 * @private
67938	 */
67939	construct: function(item, config) {
67940		var me = this;
67941
67942		config = initConfig(config);
67943
67944		var context = platform.acquireContext(item, config);
67945		var canvas = context && context.canvas;
67946		var height = canvas && canvas.height;
67947		var width = canvas && canvas.width;
67948
67949		me.id = helpers$1.uid();
67950		me.ctx = context;
67951		me.canvas = canvas;
67952		me.config = config;
67953		me.width = width;
67954		me.height = height;
67955		me.aspectRatio = height ? width / height : null;
67956		me.options = config.options;
67957		me._bufferedRender = false;
67958
67959		/**
67960		 * Provided for backward compatibility, Chart and Chart.Controller have been merged,
67961		 * the "instance" still need to be defined since it might be called from plugins.
67962		 * @prop Chart#chart
67963		 * @deprecated since version 2.6.0
67964		 * @todo remove at version 3
67965		 * @private
67966		 */
67967		me.chart = me;
67968		me.controller = me; // chart.chart.controller #inception
67969
67970		// Add the chart instance to the global namespace
67971		Chart.instances[me.id] = me;
67972
67973		// Define alias to the config data: `chart.data === chart.config.data`
67974		Object.defineProperty(me, 'data', {
67975			get: function() {
67976				return me.config.data;
67977			},
67978			set: function(value) {
67979				me.config.data = value;
67980			}
67981		});
67982
67983		if (!context || !canvas) {
67984			// The given item is not a compatible context2d element, let's return before finalizing
67985			// the chart initialization but after setting basic chart / controller properties that
67986			// can help to figure out that the chart is not valid (e.g chart.canvas !== null);
67987			// https://github.com/chartjs/Chart.js/issues/2807
67988			console.error("Failed to create chart: can't acquire context from the given item");
67989			return;
67990		}
67991
67992		me.initialize();
67993		me.update();
67994	},
67995
67996	/**
67997	 * @private
67998	 */
67999	initialize: function() {
68000		var me = this;
68001
68002		// Before init plugin notification
68003		core_plugins.notify(me, 'beforeInit');
68004
68005		helpers$1.retinaScale(me, me.options.devicePixelRatio);
68006
68007		me.bindEvents();
68008
68009		if (me.options.responsive) {
68010			// Initial resize before chart draws (must be silent to preserve initial animations).
68011			me.resize(true);
68012		}
68013
68014		// Make sure scales have IDs and are built before we build any controllers.
68015		me.ensureScalesHaveIDs();
68016		me.buildOrUpdateScales();
68017		me.initToolTip();
68018
68019		// After init plugin notification
68020		core_plugins.notify(me, 'afterInit');
68021
68022		return me;
68023	},
68024
68025	clear: function() {
68026		helpers$1.canvas.clear(this);
68027		return this;
68028	},
68029
68030	stop: function() {
68031		// Stops any current animation loop occurring
68032		core_animations.cancelAnimation(this);
68033		return this;
68034	},
68035
68036	resize: function(silent) {
68037		var me = this;
68038		var options = me.options;
68039		var canvas = me.canvas;
68040		var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null;
68041
68042		// the canvas render width and height will be casted to integers so make sure that
68043		// the canvas display style uses the same integer values to avoid blurring effect.
68044
68045		// Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collapsed
68046		var newWidth = Math.max(0, Math.floor(helpers$1.getMaximumWidth(canvas)));
68047		var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers$1.getMaximumHeight(canvas)));
68048
68049		if (me.width === newWidth && me.height === newHeight) {
68050			return;
68051		}
68052
68053		canvas.width = me.width = newWidth;
68054		canvas.height = me.height = newHeight;
68055		canvas.style.width = newWidth + 'px';
68056		canvas.style.height = newHeight + 'px';
68057
68058		helpers$1.retinaScale(me, options.devicePixelRatio);
68059
68060		if (!silent) {
68061			// Notify any plugins about the resize
68062			var newSize = {width: newWidth, height: newHeight};
68063			core_plugins.notify(me, 'resize', [newSize]);
68064
68065			// Notify of resize
68066			if (options.onResize) {
68067				options.onResize(me, newSize);
68068			}
68069
68070			me.stop();
68071			me.update({
68072				duration: options.responsiveAnimationDuration
68073			});
68074		}
68075	},
68076
68077	ensureScalesHaveIDs: function() {
68078		var options = this.options;
68079		var scalesOptions = options.scales || {};
68080		var scaleOptions = options.scale;
68081
68082		helpers$1.each(scalesOptions.xAxes, function(xAxisOptions, index) {
68083			xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);
68084		});
68085
68086		helpers$1.each(scalesOptions.yAxes, function(yAxisOptions, index) {
68087			yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);
68088		});
68089
68090		if (scaleOptions) {
68091			scaleOptions.id = scaleOptions.id || 'scale';
68092		}
68093	},
68094
68095	/**
68096	 * Builds a map of scale ID to scale object for future lookup.
68097	 */
68098	buildOrUpdateScales: function() {
68099		var me = this;
68100		var options = me.options;
68101		var scales = me.scales || {};
68102		var items = [];
68103		var updated = Object.keys(scales).reduce(function(obj, id) {
68104			obj[id] = false;
68105			return obj;
68106		}, {});
68107
68108		if (options.scales) {
68109			items = items.concat(
68110				(options.scales.xAxes || []).map(function(xAxisOptions) {
68111					return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'};
68112				}),
68113				(options.scales.yAxes || []).map(function(yAxisOptions) {
68114					return {options: yAxisOptions, dtype: 'linear', dposition: 'left'};
68115				})
68116			);
68117		}
68118
68119		if (options.scale) {
68120			items.push({
68121				options: options.scale,
68122				dtype: 'radialLinear',
68123				isDefault: true,
68124				dposition: 'chartArea'
68125			});
68126		}
68127
68128		helpers$1.each(items, function(item) {
68129			var scaleOptions = item.options;
68130			var id = scaleOptions.id;
68131			var scaleType = valueOrDefault$8(scaleOptions.type, item.dtype);
68132
68133			if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) {
68134				scaleOptions.position = item.dposition;
68135			}
68136
68137			updated[id] = true;
68138			var scale = null;
68139			if (id in scales && scales[id].type === scaleType) {
68140				scale = scales[id];
68141				scale.options = scaleOptions;
68142				scale.ctx = me.ctx;
68143				scale.chart = me;
68144			} else {
68145				var scaleClass = core_scaleService.getScaleConstructor(scaleType);
68146				if (!scaleClass) {
68147					return;
68148				}
68149				scale = new scaleClass({
68150					id: id,
68151					type: scaleType,
68152					options: scaleOptions,
68153					ctx: me.ctx,
68154					chart: me
68155				});
68156				scales[scale.id] = scale;
68157			}
68158
68159			scale.mergeTicksOptions();
68160
68161			// TODO(SB): I think we should be able to remove this custom case (options.scale)
68162			// and consider it as a regular scale part of the "scales"" map only! This would
68163			// make the logic easier and remove some useless? custom code.
68164			if (item.isDefault) {
68165				me.scale = scale;
68166			}
68167		});
68168		// clear up discarded scales
68169		helpers$1.each(updated, function(hasUpdated, id) {
68170			if (!hasUpdated) {
68171				delete scales[id];
68172			}
68173		});
68174
68175		me.scales = scales;
68176
68177		core_scaleService.addScalesToLayout(this);
68178	},
68179
68180	buildOrUpdateControllers: function() {
68181		var me = this;
68182		var newControllers = [];
68183
68184		helpers$1.each(me.data.datasets, function(dataset, datasetIndex) {
68185			var meta = me.getDatasetMeta(datasetIndex);
68186			var type = dataset.type || me.config.type;
68187
68188			if (meta.type && meta.type !== type) {
68189				me.destroyDatasetMeta(datasetIndex);
68190				meta = me.getDatasetMeta(datasetIndex);
68191			}
68192			meta.type = type;
68193
68194			if (meta.controller) {
68195				meta.controller.updateIndex(datasetIndex);
68196				meta.controller.linkScales();
68197			} else {
68198				var ControllerClass = controllers[meta.type];
68199				if (ControllerClass === undefined) {
68200					throw new Error('"' + meta.type + '" is not a chart type.');
68201				}
68202
68203				meta.controller = new ControllerClass(me, datasetIndex);
68204				newControllers.push(meta.controller);
68205			}
68206		}, me);
68207
68208		return newControllers;
68209	},
68210
68211	/**
68212	 * Reset the elements of all datasets
68213	 * @private
68214	 */
68215	resetElements: function() {
68216		var me = this;
68217		helpers$1.each(me.data.datasets, function(dataset, datasetIndex) {
68218			me.getDatasetMeta(datasetIndex).controller.reset();
68219		}, me);
68220	},
68221
68222	/**
68223	* Resets the chart back to it's state before the initial animation
68224	*/
68225	reset: function() {
68226		this.resetElements();
68227		this.tooltip.initialize();
68228	},
68229
68230	update: function(config) {
68231		var me = this;
68232
68233		if (!config || typeof config !== 'object') {
68234			// backwards compatibility
68235			config = {
68236				duration: config,
68237				lazy: arguments[1]
68238			};
68239		}
68240
68241		updateConfig(me);
68242
68243		// plugins options references might have change, let's invalidate the cache
68244		// https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167
68245		core_plugins._invalidate(me);
68246
68247		if (core_plugins.notify(me, 'beforeUpdate') === false) {
68248			return;
68249		}
68250
68251		// In case the entire data object changed
68252		me.tooltip._data = me.data;
68253
68254		// Make sure dataset controllers are updated and new controllers are reset
68255		var newControllers = me.buildOrUpdateControllers();
68256
68257		// Make sure all dataset controllers have correct meta data counts
68258		helpers$1.each(me.data.datasets, function(dataset, datasetIndex) {
68259			me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();
68260		}, me);
68261
68262		me.updateLayout();
68263
68264		// Can only reset the new controllers after the scales have been updated
68265		if (me.options.animation && me.options.animation.duration) {
68266			helpers$1.each(newControllers, function(controller) {
68267				controller.reset();
68268			});
68269		}
68270
68271		me.updateDatasets();
68272
68273		// Need to reset tooltip in case it is displayed with elements that are removed
68274		// after update.
68275		me.tooltip.initialize();
68276
68277		// Last active contains items that were previously in the tooltip.
68278		// When we reset the tooltip, we need to clear it
68279		me.lastActive = [];
68280
68281		// Do this before render so that any plugins that need final scale updates can use it
68282		core_plugins.notify(me, 'afterUpdate');
68283
68284		if (me._bufferedRender) {
68285			me._bufferedRequest = {
68286				duration: config.duration,
68287				easing: config.easing,
68288				lazy: config.lazy
68289			};
68290		} else {
68291			me.render(config);
68292		}
68293	},
68294
68295	/**
68296	 * Updates the chart layout unless a plugin returns `false` to the `beforeLayout`
68297	 * hook, in which case, plugins will not be called on `afterLayout`.
68298	 * @private
68299	 */
68300	updateLayout: function() {
68301		var me = this;
68302
68303		if (core_plugins.notify(me, 'beforeLayout') === false) {
68304			return;
68305		}
68306
68307		core_layouts.update(this, this.width, this.height);
68308
68309		/**
68310		 * Provided for backward compatibility, use `afterLayout` instead.
68311		 * @method IPlugin#afterScaleUpdate
68312		 * @deprecated since version 2.5.0
68313		 * @todo remove at version 3
68314		 * @private
68315		 */
68316		core_plugins.notify(me, 'afterScaleUpdate');
68317		core_plugins.notify(me, 'afterLayout');
68318	},
68319
68320	/**
68321	 * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate`
68322	 * hook, in which case, plugins will not be called on `afterDatasetsUpdate`.
68323	 * @private
68324	 */
68325	updateDatasets: function() {
68326		var me = this;
68327
68328		if (core_plugins.notify(me, 'beforeDatasetsUpdate') === false) {
68329			return;
68330		}
68331
68332		for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
68333			me.updateDataset(i);
68334		}
68335
68336		core_plugins.notify(me, 'afterDatasetsUpdate');
68337	},
68338
68339	/**
68340	 * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate`
68341	 * hook, in which case, plugins will not be called on `afterDatasetUpdate`.
68342	 * @private
68343	 */
68344	updateDataset: function(index) {
68345		var me = this;
68346		var meta = me.getDatasetMeta(index);
68347		var args = {
68348			meta: meta,
68349			index: index
68350		};
68351
68352		if (core_plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) {
68353			return;
68354		}
68355
68356		meta.controller.update();
68357
68358		core_plugins.notify(me, 'afterDatasetUpdate', [args]);
68359	},
68360
68361	render: function(config) {
68362		var me = this;
68363
68364		if (!config || typeof config !== 'object') {
68365			// backwards compatibility
68366			config = {
68367				duration: config,
68368				lazy: arguments[1]
68369			};
68370		}
68371
68372		var animationOptions = me.options.animation;
68373		var duration = valueOrDefault$8(config.duration, animationOptions && animationOptions.duration);
68374		var lazy = config.lazy;
68375
68376		if (core_plugins.notify(me, 'beforeRender') === false) {
68377			return;
68378		}
68379
68380		var onComplete = function(animation) {
68381			core_plugins.notify(me, 'afterRender');
68382			helpers$1.callback(animationOptions && animationOptions.onComplete, [animation], me);
68383		};
68384
68385		if (animationOptions && duration) {
68386			var animation = new core_animation({
68387				numSteps: duration / 16.66, // 60 fps
68388				easing: config.easing || animationOptions.easing,
68389
68390				render: function(chart, animationObject) {
68391					var easingFunction = helpers$1.easing.effects[animationObject.easing];
68392					var currentStep = animationObject.currentStep;
68393					var stepDecimal = currentStep / animationObject.numSteps;
68394
68395					chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep);
68396				},
68397
68398				onAnimationProgress: animationOptions.onProgress,
68399				onAnimationComplete: onComplete
68400			});
68401
68402			core_animations.addAnimation(me, animation, duration, lazy);
68403		} else {
68404			me.draw();
68405
68406			// See https://github.com/chartjs/Chart.js/issues/3781
68407			onComplete(new core_animation({numSteps: 0, chart: me}));
68408		}
68409
68410		return me;
68411	},
68412
68413	draw: function(easingValue) {
68414		var me = this;
68415
68416		me.clear();
68417
68418		if (helpers$1.isNullOrUndef(easingValue)) {
68419			easingValue = 1;
68420		}
68421
68422		me.transition(easingValue);
68423
68424		if (me.width <= 0 || me.height <= 0) {
68425			return;
68426		}
68427
68428		if (core_plugins.notify(me, 'beforeDraw', [easingValue]) === false) {
68429			return;
68430		}
68431
68432		// Draw all the scales
68433		helpers$1.each(me.boxes, function(box) {
68434			box.draw(me.chartArea);
68435		}, me);
68436
68437		me.drawDatasets(easingValue);
68438		me._drawTooltip(easingValue);
68439
68440		core_plugins.notify(me, 'afterDraw', [easingValue]);
68441	},
68442
68443	/**
68444	 * @private
68445	 */
68446	transition: function(easingValue) {
68447		var me = this;
68448
68449		for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) {
68450			if (me.isDatasetVisible(i)) {
68451				me.getDatasetMeta(i).controller.transition(easingValue);
68452			}
68453		}
68454
68455		me.tooltip.transition(easingValue);
68456	},
68457
68458	/**
68459	 * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw`
68460	 * hook, in which case, plugins will not be called on `afterDatasetsDraw`.
68461	 * @private
68462	 */
68463	drawDatasets: function(easingValue) {
68464		var me = this;
68465
68466		if (core_plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {
68467			return;
68468		}
68469
68470		// Draw datasets reversed to support proper line stacking
68471		for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) {
68472			if (me.isDatasetVisible(i)) {
68473				me.drawDataset(i, easingValue);
68474			}
68475		}
68476
68477		core_plugins.notify(me, 'afterDatasetsDraw', [easingValue]);
68478	},
68479
68480	/**
68481	 * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw`
68482	 * hook, in which case, plugins will not be called on `afterDatasetDraw`.
68483	 * @private
68484	 */
68485	drawDataset: function(index, easingValue) {
68486		var me = this;
68487		var meta = me.getDatasetMeta(index);
68488		var args = {
68489			meta: meta,
68490			index: index,
68491			easingValue: easingValue
68492		};
68493
68494		if (core_plugins.notify(me, 'beforeDatasetDraw', [args]) === false) {
68495			return;
68496		}
68497
68498		meta.controller.draw(easingValue);
68499
68500		core_plugins.notify(me, 'afterDatasetDraw', [args]);
68501	},
68502
68503	/**
68504	 * Draws tooltip unless a plugin returns `false` to the `beforeTooltipDraw`
68505	 * hook, in which case, plugins will not be called on `afterTooltipDraw`.
68506	 * @private
68507	 */
68508	_drawTooltip: function(easingValue) {
68509		var me = this;
68510		var tooltip = me.tooltip;
68511		var args = {
68512			tooltip: tooltip,
68513			easingValue: easingValue
68514		};
68515
68516		if (core_plugins.notify(me, 'beforeTooltipDraw', [args]) === false) {
68517			return;
68518		}
68519
68520		tooltip.draw();
68521
68522		core_plugins.notify(me, 'afterTooltipDraw', [args]);
68523	},
68524
68525	/**
68526	 * Get the single element that was clicked on
68527	 * @return An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw
68528	 */
68529	getElementAtEvent: function(e) {
68530		return core_interaction.modes.single(this, e);
68531	},
68532
68533	getElementsAtEvent: function(e) {
68534		return core_interaction.modes.label(this, e, {intersect: true});
68535	},
68536
68537	getElementsAtXAxis: function(e) {
68538		return core_interaction.modes['x-axis'](this, e, {intersect: true});
68539	},
68540
68541	getElementsAtEventForMode: function(e, mode, options) {
68542		var method = core_interaction.modes[mode];
68543		if (typeof method === 'function') {
68544			return method(this, e, options);
68545		}
68546
68547		return [];
68548	},
68549
68550	getDatasetAtEvent: function(e) {
68551		return core_interaction.modes.dataset(this, e, {intersect: true});
68552	},
68553
68554	getDatasetMeta: function(datasetIndex) {
68555		var me = this;
68556		var dataset = me.data.datasets[datasetIndex];
68557		if (!dataset._meta) {
68558			dataset._meta = {};
68559		}
68560
68561		var meta = dataset._meta[me.id];
68562		if (!meta) {
68563			meta = dataset._meta[me.id] = {
68564				type: null,
68565				data: [],
68566				dataset: null,
68567				controller: null,
68568				hidden: null,			// See isDatasetVisible() comment
68569				xAxisID: null,
68570				yAxisID: null
68571			};
68572		}
68573
68574		return meta;
68575	},
68576
68577	getVisibleDatasetCount: function() {
68578		var count = 0;
68579		for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
68580			if (this.isDatasetVisible(i)) {
68581				count++;
68582			}
68583		}
68584		return count;
68585	},
68586
68587	isDatasetVisible: function(datasetIndex) {
68588		var meta = this.getDatasetMeta(datasetIndex);
68589
68590		// meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
68591		// the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
68592		return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
68593	},
68594
68595	generateLegend: function() {
68596		return this.options.legendCallback(this);
68597	},
68598
68599	/**
68600	 * @private
68601	 */
68602	destroyDatasetMeta: function(datasetIndex) {
68603		var id = this.id;
68604		var dataset = this.data.datasets[datasetIndex];
68605		var meta = dataset._meta && dataset._meta[id];
68606
68607		if (meta) {
68608			meta.controller.destroy();
68609			delete dataset._meta[id];
68610		}
68611	},
68612
68613	destroy: function() {
68614		var me = this;
68615		var canvas = me.canvas;
68616		var i, ilen;
68617
68618		me.stop();
68619
68620		// dataset controllers need to cleanup associated data
68621		for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {
68622			me.destroyDatasetMeta(i);
68623		}
68624
68625		if (canvas) {
68626			me.unbindEvents();
68627			helpers$1.canvas.clear(me);
68628			platform.releaseContext(me.ctx);
68629			me.canvas = null;
68630			me.ctx = null;
68631		}
68632
68633		core_plugins.notify(me, 'destroy');
68634
68635		delete Chart.instances[me.id];
68636	},
68637
68638	toBase64Image: function() {
68639		return this.canvas.toDataURL.apply(this.canvas, arguments);
68640	},
68641
68642	initToolTip: function() {
68643		var me = this;
68644		me.tooltip = new core_tooltip({
68645			_chart: me,
68646			_chartInstance: me, // deprecated, backward compatibility
68647			_data: me.data,
68648			_options: me.options.tooltips
68649		}, me);
68650	},
68651
68652	/**
68653	 * @private
68654	 */
68655	bindEvents: function() {
68656		var me = this;
68657		var listeners = me._listeners = {};
68658		var listener = function() {
68659			me.eventHandler.apply(me, arguments);
68660		};
68661
68662		helpers$1.each(me.options.events, function(type) {
68663			platform.addEventListener(me, type, listener);
68664			listeners[type] = listener;
68665		});
68666
68667		// Elements used to detect size change should not be injected for non responsive charts.
68668		// See https://github.com/chartjs/Chart.js/issues/2210
68669		if (me.options.responsive) {
68670			listener = function() {
68671				me.resize();
68672			};
68673
68674			platform.addEventListener(me, 'resize', listener);
68675			listeners.resize = listener;
68676		}
68677	},
68678
68679	/**
68680	 * @private
68681	 */
68682	unbindEvents: function() {
68683		var me = this;
68684		var listeners = me._listeners;
68685		if (!listeners) {
68686			return;
68687		}
68688
68689		delete me._listeners;
68690		helpers$1.each(listeners, function(listener, type) {
68691			platform.removeEventListener(me, type, listener);
68692		});
68693	},
68694
68695	updateHoverStyle: function(elements, mode, enabled) {
68696		var method = enabled ? 'setHoverStyle' : 'removeHoverStyle';
68697		var element, i, ilen;
68698
68699		for (i = 0, ilen = elements.length; i < ilen; ++i) {
68700			element = elements[i];
68701			if (element) {
68702				this.getDatasetMeta(element._datasetIndex).controller[method](element);
68703			}
68704		}
68705	},
68706
68707	/**
68708	 * @private
68709	 */
68710	eventHandler: function(e) {
68711		var me = this;
68712		var tooltip = me.tooltip;
68713
68714		if (core_plugins.notify(me, 'beforeEvent', [e]) === false) {
68715			return;
68716		}
68717
68718		// Buffer any update calls so that renders do not occur
68719		me._bufferedRender = true;
68720		me._bufferedRequest = null;
68721
68722		var changed = me.handleEvent(e);
68723		// for smooth tooltip animations issue #4989
68724		// the tooltip should be the source of change
68725		// Animation check workaround:
68726		// tooltip._start will be null when tooltip isn't animating
68727		if (tooltip) {
68728			changed = tooltip._start
68729				? tooltip.handleEvent(e)
68730				: changed | tooltip.handleEvent(e);
68731		}
68732
68733		core_plugins.notify(me, 'afterEvent', [e]);
68734
68735		var bufferedRequest = me._bufferedRequest;
68736		if (bufferedRequest) {
68737			// If we have an update that was triggered, we need to do a normal render
68738			me.render(bufferedRequest);
68739		} else if (changed && !me.animating) {
68740			// If entering, leaving, or changing elements, animate the change via pivot
68741			me.stop();
68742
68743			// We only need to render at this point. Updating will cause scales to be
68744			// recomputed generating flicker & using more memory than necessary.
68745			me.render({
68746				duration: me.options.hover.animationDuration,
68747				lazy: true
68748			});
68749		}
68750
68751		me._bufferedRender = false;
68752		me._bufferedRequest = null;
68753
68754		return me;
68755	},
68756
68757	/**
68758	 * Handle an event
68759	 * @private
68760	 * @param {IEvent} event the event to handle
68761	 * @return {boolean} true if the chart needs to re-render
68762	 */
68763	handleEvent: function(e) {
68764		var me = this;
68765		var options = me.options || {};
68766		var hoverOptions = options.hover;
68767		var changed = false;
68768
68769		me.lastActive = me.lastActive || [];
68770
68771		// Find Active Elements for hover and tooltips
68772		if (e.type === 'mouseout') {
68773			me.active = [];
68774		} else {
68775			me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions);
68776		}
68777
68778		// Invoke onHover hook
68779		// Need to call with native event here to not break backwards compatibility
68780		helpers$1.callback(options.onHover || options.hover.onHover, [e.native, me.active], me);
68781
68782		if (e.type === 'mouseup' || e.type === 'click') {
68783			if (options.onClick) {
68784				// Use e.native here for backwards compatibility
68785				options.onClick.call(me, e.native, me.active);
68786			}
68787		}
68788
68789		// Remove styling for last active (even if it may still be active)
68790		if (me.lastActive.length) {
68791			me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);
68792		}
68793
68794		// Built in hover styling
68795		if (me.active.length && hoverOptions.mode) {
68796			me.updateHoverStyle(me.active, hoverOptions.mode, true);
68797		}
68798
68799		changed = !helpers$1.arrayEquals(me.active, me.lastActive);
68800
68801		// Remember Last Actives
68802		me.lastActive = me.active;
68803
68804		return changed;
68805	}
68806});
68807
68808/**
68809 * NOTE(SB) We actually don't use this container anymore but we need to keep it
68810 * for backward compatibility. Though, it can still be useful for plugins that
68811 * would need to work on multiple charts?!
68812 */
68813Chart.instances = {};
68814
68815var core_controller = Chart;
68816
68817// DEPRECATIONS
68818
68819/**
68820 * Provided for backward compatibility, use Chart instead.
68821 * @class Chart.Controller
68822 * @deprecated since version 2.6
68823 * @todo remove at version 3
68824 * @private
68825 */
68826Chart.Controller = Chart;
68827
68828/**
68829 * Provided for backward compatibility, not available anymore.
68830 * @namespace Chart
68831 * @deprecated since version 2.8
68832 * @todo remove at version 3
68833 * @private
68834 */
68835Chart.types = {};
68836
68837/**
68838 * Provided for backward compatibility, not available anymore.
68839 * @namespace Chart.helpers.configMerge
68840 * @deprecated since version 2.8.0
68841 * @todo remove at version 3
68842 * @private
68843 */
68844helpers$1.configMerge = mergeConfig;
68845
68846/**
68847 * Provided for backward compatibility, not available anymore.
68848 * @namespace Chart.helpers.scaleMerge
68849 * @deprecated since version 2.8.0
68850 * @todo remove at version 3
68851 * @private
68852 */
68853helpers$1.scaleMerge = mergeScaleConfig;
68854
68855var core_helpers = function() {
68856
68857	// -- Basic js utility methods
68858
68859	helpers$1.where = function(collection, filterCallback) {
68860		if (helpers$1.isArray(collection) && Array.prototype.filter) {
68861			return collection.filter(filterCallback);
68862		}
68863		var filtered = [];
68864
68865		helpers$1.each(collection, function(item) {
68866			if (filterCallback(item)) {
68867				filtered.push(item);
68868			}
68869		});
68870
68871		return filtered;
68872	};
68873	helpers$1.findIndex = Array.prototype.findIndex ?
68874		function(array, callback, scope) {
68875			return array.findIndex(callback, scope);
68876		} :
68877		function(array, callback, scope) {
68878			scope = scope === undefined ? array : scope;
68879			for (var i = 0, ilen = array.length; i < ilen; ++i) {
68880				if (callback.call(scope, array[i], i, array)) {
68881					return i;
68882				}
68883			}
68884			return -1;
68885		};
68886	helpers$1.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {
68887		// Default to start of the array
68888		if (helpers$1.isNullOrUndef(startIndex)) {
68889			startIndex = -1;
68890		}
68891		for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
68892			var currentItem = arrayToSearch[i];
68893			if (filterCallback(currentItem)) {
68894				return currentItem;
68895			}
68896		}
68897	};
68898	helpers$1.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {
68899		// Default to end of the array
68900		if (helpers$1.isNullOrUndef(startIndex)) {
68901			startIndex = arrayToSearch.length;
68902		}
68903		for (var i = startIndex - 1; i >= 0; i--) {
68904			var currentItem = arrayToSearch[i];
68905			if (filterCallback(currentItem)) {
68906				return currentItem;
68907			}
68908		}
68909	};
68910
68911	// -- Math methods
68912	helpers$1.isNumber = function(n) {
68913		return !isNaN(parseFloat(n)) && isFinite(n);
68914	};
68915	helpers$1.almostEquals = function(x, y, epsilon) {
68916		return Math.abs(x - y) < epsilon;
68917	};
68918	helpers$1.almostWhole = function(x, epsilon) {
68919		var rounded = Math.round(x);
68920		return (((rounded - epsilon) < x) && ((rounded + epsilon) > x));
68921	};
68922	helpers$1.max = function(array) {
68923		return array.reduce(function(max, value) {
68924			if (!isNaN(value)) {
68925				return Math.max(max, value);
68926			}
68927			return max;
68928		}, Number.NEGATIVE_INFINITY);
68929	};
68930	helpers$1.min = function(array) {
68931		return array.reduce(function(min, value) {
68932			if (!isNaN(value)) {
68933				return Math.min(min, value);
68934			}
68935			return min;
68936		}, Number.POSITIVE_INFINITY);
68937	};
68938	helpers$1.sign = Math.sign ?
68939		function(x) {
68940			return Math.sign(x);
68941		} :
68942		function(x) {
68943			x = +x; // convert to a number
68944			if (x === 0 || isNaN(x)) {
68945				return x;
68946			}
68947			return x > 0 ? 1 : -1;
68948		};
68949	helpers$1.log10 = Math.log10 ?
68950		function(x) {
68951			return Math.log10(x);
68952		} :
68953		function(x) {
68954			var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10.
68955			// Check for whole powers of 10,
68956			// which due to floating point rounding error should be corrected.
68957			var powerOf10 = Math.round(exponent);
68958			var isPowerOf10 = x === Math.pow(10, powerOf10);
68959
68960			return isPowerOf10 ? powerOf10 : exponent;
68961		};
68962	helpers$1.toRadians = function(degrees) {
68963		return degrees * (Math.PI / 180);
68964	};
68965	helpers$1.toDegrees = function(radians) {
68966		return radians * (180 / Math.PI);
68967	};
68968
68969	/**
68970	 * Returns the number of decimal places
68971	 * i.e. the number of digits after the decimal point, of the value of this Number.
68972	 * @param {number} x - A number.
68973	 * @returns {number} The number of decimal places.
68974	 * @private
68975	 */
68976	helpers$1._decimalPlaces = function(x) {
68977		if (!helpers$1.isFinite(x)) {
68978			return;
68979		}
68980		var e = 1;
68981		var p = 0;
68982		while (Math.round(x * e) / e !== x) {
68983			e *= 10;
68984			p++;
68985		}
68986		return p;
68987	};
68988
68989	// Gets the angle from vertical upright to the point about a centre.
68990	helpers$1.getAngleFromPoint = function(centrePoint, anglePoint) {
68991		var distanceFromXCenter = anglePoint.x - centrePoint.x;
68992		var distanceFromYCenter = anglePoint.y - centrePoint.y;
68993		var radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
68994
68995		var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
68996
68997		if (angle < (-0.5 * Math.PI)) {
68998			angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
68999		}
69000
69001		return {
69002			angle: angle,
69003			distance: radialDistanceFromCenter
69004		};
69005	};
69006	helpers$1.distanceBetweenPoints = function(pt1, pt2) {
69007		return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
69008	};
69009
69010	/**
69011	 * Provided for backward compatibility, not available anymore
69012	 * @function Chart.helpers.aliasPixel
69013	 * @deprecated since version 2.8.0
69014	 * @todo remove at version 3
69015	 */
69016	helpers$1.aliasPixel = function(pixelWidth) {
69017		return (pixelWidth % 2 === 0) ? 0 : 0.5;
69018	};
69019
69020	/**
69021	 * Returns the aligned pixel value to avoid anti-aliasing blur
69022	 * @param {Chart} chart - The chart instance.
69023	 * @param {number} pixel - A pixel value.
69024	 * @param {number} width - The width of the element.
69025	 * @returns {number} The aligned pixel value.
69026	 * @private
69027	 */
69028	helpers$1._alignPixel = function(chart, pixel, width) {
69029		var devicePixelRatio = chart.currentDevicePixelRatio;
69030		var halfWidth = width / 2;
69031		return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;
69032	};
69033
69034	helpers$1.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
69035		// Props to Rob Spencer at scaled innovation for his post on splining between points
69036		// http://scaledinnovation.com/analytics/splines/aboutSplines.html
69037
69038		// This function must also respect "skipped" points
69039
69040		var previous = firstPoint.skip ? middlePoint : firstPoint;
69041		var current = middlePoint;
69042		var next = afterPoint.skip ? middlePoint : afterPoint;
69043
69044		var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
69045		var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
69046
69047		var s01 = d01 / (d01 + d12);
69048		var s12 = d12 / (d01 + d12);
69049
69050		// If all points are the same, s01 & s02 will be inf
69051		s01 = isNaN(s01) ? 0 : s01;
69052		s12 = isNaN(s12) ? 0 : s12;
69053
69054		var fa = t * s01; // scaling factor for triangle Ta
69055		var fb = t * s12;
69056
69057		return {
69058			previous: {
69059				x: current.x - fa * (next.x - previous.x),
69060				y: current.y - fa * (next.y - previous.y)
69061			},
69062			next: {
69063				x: current.x + fb * (next.x - previous.x),
69064				y: current.y + fb * (next.y - previous.y)
69065			}
69066		};
69067	};
69068	helpers$1.EPSILON = Number.EPSILON || 1e-14;
69069	helpers$1.splineCurveMonotone = function(points) {
69070		// This function calculates Bézier control points in a similar way than |splineCurve|,
69071		// but preserves monotonicity of the provided data and ensures no local extremums are added
69072		// between the dataset discrete points due to the interpolation.
69073		// See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
69074
69075		var pointsWithTangents = (points || []).map(function(point) {
69076			return {
69077				model: point._model,
69078				deltaK: 0,
69079				mK: 0
69080			};
69081		});
69082
69083		// Calculate slopes (deltaK) and initialize tangents (mK)
69084		var pointsLen = pointsWithTangents.length;
69085		var i, pointBefore, pointCurrent, pointAfter;
69086		for (i = 0; i < pointsLen; ++i) {
69087			pointCurrent = pointsWithTangents[i];
69088			if (pointCurrent.model.skip) {
69089				continue;
69090			}
69091
69092			pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
69093			pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
69094			if (pointAfter && !pointAfter.model.skip) {
69095				var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x);
69096
69097				// In the case of two points that appear at the same x pixel, slopeDeltaX is 0
69098				pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0;
69099			}
69100
69101			if (!pointBefore || pointBefore.model.skip) {
69102				pointCurrent.mK = pointCurrent.deltaK;
69103			} else if (!pointAfter || pointAfter.model.skip) {
69104				pointCurrent.mK = pointBefore.deltaK;
69105			} else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) {
69106				pointCurrent.mK = 0;
69107			} else {
69108				pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2;
69109			}
69110		}
69111
69112		// Adjust tangents to ensure monotonic properties
69113		var alphaK, betaK, tauK, squaredMagnitude;
69114		for (i = 0; i < pointsLen - 1; ++i) {
69115			pointCurrent = pointsWithTangents[i];
69116			pointAfter = pointsWithTangents[i + 1];
69117			if (pointCurrent.model.skip || pointAfter.model.skip) {
69118				continue;
69119			}
69120
69121			if (helpers$1.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) {
69122				pointCurrent.mK = pointAfter.mK = 0;
69123				continue;
69124			}
69125
69126			alphaK = pointCurrent.mK / pointCurrent.deltaK;
69127			betaK = pointAfter.mK / pointCurrent.deltaK;
69128			squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
69129			if (squaredMagnitude <= 9) {
69130				continue;
69131			}
69132
69133			tauK = 3 / Math.sqrt(squaredMagnitude);
69134			pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK;
69135			pointAfter.mK = betaK * tauK * pointCurrent.deltaK;
69136		}
69137
69138		// Compute control points
69139		var deltaX;
69140		for (i = 0; i < pointsLen; ++i) {
69141			pointCurrent = pointsWithTangents[i];
69142			if (pointCurrent.model.skip) {
69143				continue;
69144			}
69145
69146			pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
69147			pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
69148			if (pointBefore && !pointBefore.model.skip) {
69149				deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3;
69150				pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX;
69151				pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK;
69152			}
69153			if (pointAfter && !pointAfter.model.skip) {
69154				deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3;
69155				pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX;
69156				pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK;
69157			}
69158		}
69159	};
69160	helpers$1.nextItem = function(collection, index, loop) {
69161		if (loop) {
69162			return index >= collection.length - 1 ? collection[0] : collection[index + 1];
69163		}
69164		return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];
69165	};
69166	helpers$1.previousItem = function(collection, index, loop) {
69167		if (loop) {
69168			return index <= 0 ? collection[collection.length - 1] : collection[index - 1];
69169		}
69170		return index <= 0 ? collection[0] : collection[index - 1];
69171	};
69172	// Implementation of the nice number algorithm used in determining where axis labels will go
69173	helpers$1.niceNum = function(range, round) {
69174		var exponent = Math.floor(helpers$1.log10(range));
69175		var fraction = range / Math.pow(10, exponent);
69176		var niceFraction;
69177
69178		if (round) {
69179			if (fraction < 1.5) {
69180				niceFraction = 1;
69181			} else if (fraction < 3) {
69182				niceFraction = 2;
69183			} else if (fraction < 7) {
69184				niceFraction = 5;
69185			} else {
69186				niceFraction = 10;
69187			}
69188		} else if (fraction <= 1.0) {
69189			niceFraction = 1;
69190		} else if (fraction <= 2) {
69191			niceFraction = 2;
69192		} else if (fraction <= 5) {
69193			niceFraction = 5;
69194		} else {
69195			niceFraction = 10;
69196		}
69197
69198		return niceFraction * Math.pow(10, exponent);
69199	};
69200	// Request animation polyfill - https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
69201	helpers$1.requestAnimFrame = (function() {
69202		if (typeof window === 'undefined') {
69203			return function(callback) {
69204				callback();
69205			};
69206		}
69207		return window.requestAnimationFrame ||
69208			window.webkitRequestAnimationFrame ||
69209			window.mozRequestAnimationFrame ||
69210			window.oRequestAnimationFrame ||
69211			window.msRequestAnimationFrame ||
69212			function(callback) {
69213				return window.setTimeout(callback, 1000 / 60);
69214			};
69215	}());
69216	// -- DOM methods
69217	helpers$1.getRelativePosition = function(evt, chart) {
69218		var mouseX, mouseY;
69219		var e = evt.originalEvent || evt;
69220		var canvas = evt.target || evt.srcElement;
69221		var boundingRect = canvas.getBoundingClientRect();
69222
69223		var touches = e.touches;
69224		if (touches && touches.length > 0) {
69225			mouseX = touches[0].clientX;
69226			mouseY = touches[0].clientY;
69227
69228		} else {
69229			mouseX = e.clientX;
69230			mouseY = e.clientY;
69231		}
69232
69233		// Scale mouse coordinates into canvas coordinates
69234		// by following the pattern laid out by 'jerryj' in the comments of
69235		// https://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
69236		var paddingLeft = parseFloat(helpers$1.getStyle(canvas, 'padding-left'));
69237		var paddingTop = parseFloat(helpers$1.getStyle(canvas, 'padding-top'));
69238		var paddingRight = parseFloat(helpers$1.getStyle(canvas, 'padding-right'));
69239		var paddingBottom = parseFloat(helpers$1.getStyle(canvas, 'padding-bottom'));
69240		var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;
69241		var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;
69242
69243		// We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
69244		// the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here
69245		mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);
69246		mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);
69247
69248		return {
69249			x: mouseX,
69250			y: mouseY
69251		};
69252
69253	};
69254
69255	// Private helper function to convert max-width/max-height values that may be percentages into a number
69256	function parseMaxStyle(styleValue, node, parentProperty) {
69257		var valueInPixels;
69258		if (typeof styleValue === 'string') {
69259			valueInPixels = parseInt(styleValue, 10);
69260
69261			if (styleValue.indexOf('%') !== -1) {
69262				// percentage * size in dimension
69263				valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
69264			}
69265		} else {
69266			valueInPixels = styleValue;
69267		}
69268
69269		return valueInPixels;
69270	}
69271
69272	/**
69273	 * Returns if the given value contains an effective constraint.
69274	 * @private
69275	 */
69276	function isConstrainedValue(value) {
69277		return value !== undefined && value !== null && value !== 'none';
69278	}
69279
69280	/**
69281	 * Returns the max width or height of the given DOM node in a cross-browser compatible fashion
69282	 * @param {HTMLElement} domNode - the node to check the constraint on
69283	 * @param {string} maxStyle - the style that defines the maximum for the direction we are using ('max-width' / 'max-height')
69284	 * @param {string} percentageProperty - property of parent to use when calculating width as a percentage
69285	 * @see {@link https://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser}
69286	 */
69287	function getConstraintDimension(domNode, maxStyle, percentageProperty) {
69288		var view = document.defaultView;
69289		var parentNode = helpers$1._getParentNode(domNode);
69290		var constrainedNode = view.getComputedStyle(domNode)[maxStyle];
69291		var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];
69292		var hasCNode = isConstrainedValue(constrainedNode);
69293		var hasCContainer = isConstrainedValue(constrainedContainer);
69294		var infinity = Number.POSITIVE_INFINITY;
69295
69296		if (hasCNode || hasCContainer) {
69297			return Math.min(
69298				hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,
69299				hasCContainer ? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);
69300		}
69301
69302		return 'none';
69303	}
69304	// returns Number or undefined if no constraint
69305	helpers$1.getConstraintWidth = function(domNode) {
69306		return getConstraintDimension(domNode, 'max-width', 'clientWidth');
69307	};
69308	// returns Number or undefined if no constraint
69309	helpers$1.getConstraintHeight = function(domNode) {
69310		return getConstraintDimension(domNode, 'max-height', 'clientHeight');
69311	};
69312	/**
69313	 * @private
69314 	 */
69315	helpers$1._calculatePadding = function(container, padding, parentDimension) {
69316		padding = helpers$1.getStyle(container, padding);
69317
69318		return padding.indexOf('%') > -1 ? parentDimension * parseInt(padding, 10) / 100 : parseInt(padding, 10);
69319	};
69320	/**
69321	 * @private
69322	 */
69323	helpers$1._getParentNode = function(domNode) {
69324		var parent = domNode.parentNode;
69325		if (parent && parent.toString() === '[object ShadowRoot]') {
69326			parent = parent.host;
69327		}
69328		return parent;
69329	};
69330	helpers$1.getMaximumWidth = function(domNode) {
69331		var container = helpers$1._getParentNode(domNode);
69332		if (!container) {
69333			return domNode.clientWidth;
69334		}
69335
69336		var clientWidth = container.clientWidth;
69337		var paddingLeft = helpers$1._calculatePadding(container, 'padding-left', clientWidth);
69338		var paddingRight = helpers$1._calculatePadding(container, 'padding-right', clientWidth);
69339
69340		var w = clientWidth - paddingLeft - paddingRight;
69341		var cw = helpers$1.getConstraintWidth(domNode);
69342		return isNaN(cw) ? w : Math.min(w, cw);
69343	};
69344	helpers$1.getMaximumHeight = function(domNode) {
69345		var container = helpers$1._getParentNode(domNode);
69346		if (!container) {
69347			return domNode.clientHeight;
69348		}
69349
69350		var clientHeight = container.clientHeight;
69351		var paddingTop = helpers$1._calculatePadding(container, 'padding-top', clientHeight);
69352		var paddingBottom = helpers$1._calculatePadding(container, 'padding-bottom', clientHeight);
69353
69354		var h = clientHeight - paddingTop - paddingBottom;
69355		var ch = helpers$1.getConstraintHeight(domNode);
69356		return isNaN(ch) ? h : Math.min(h, ch);
69357	};
69358	helpers$1.getStyle = function(el, property) {
69359		return el.currentStyle ?
69360			el.currentStyle[property] :
69361			document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
69362	};
69363	helpers$1.retinaScale = function(chart, forceRatio) {
69364		var pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof window !== 'undefined' && window.devicePixelRatio) || 1;
69365		if (pixelRatio === 1) {
69366			return;
69367		}
69368
69369		var canvas = chart.canvas;
69370		var height = chart.height;
69371		var width = chart.width;
69372
69373		canvas.height = height * pixelRatio;
69374		canvas.width = width * pixelRatio;
69375		chart.ctx.scale(pixelRatio, pixelRatio);
69376
69377		// If no style has been set on the canvas, the render size is used as display size,
69378		// making the chart visually bigger, so let's enforce it to the "correct" values.
69379		// See https://github.com/chartjs/Chart.js/issues/3575
69380		if (!canvas.style.height && !canvas.style.width) {
69381			canvas.style.height = height + 'px';
69382			canvas.style.width = width + 'px';
69383		}
69384	};
69385	// -- Canvas methods
69386	helpers$1.fontString = function(pixelSize, fontStyle, fontFamily) {
69387		return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
69388	};
69389	helpers$1.longestText = function(ctx, font, arrayOfThings, cache) {
69390		cache = cache || {};
69391		var data = cache.data = cache.data || {};
69392		var gc = cache.garbageCollect = cache.garbageCollect || [];
69393
69394		if (cache.font !== font) {
69395			data = cache.data = {};
69396			gc = cache.garbageCollect = [];
69397			cache.font = font;
69398		}
69399
69400		ctx.font = font;
69401		var longest = 0;
69402		helpers$1.each(arrayOfThings, function(thing) {
69403			// Undefined strings and arrays should not be measured
69404			if (thing !== undefined && thing !== null && helpers$1.isArray(thing) !== true) {
69405				longest = helpers$1.measureText(ctx, data, gc, longest, thing);
69406			} else if (helpers$1.isArray(thing)) {
69407				// if it is an array lets measure each element
69408				// to do maybe simplify this function a bit so we can do this more recursively?
69409				helpers$1.each(thing, function(nestedThing) {
69410					// Undefined strings and arrays should not be measured
69411					if (nestedThing !== undefined && nestedThing !== null && !helpers$1.isArray(nestedThing)) {
69412						longest = helpers$1.measureText(ctx, data, gc, longest, nestedThing);
69413					}
69414				});
69415			}
69416		});
69417
69418		var gcLen = gc.length / 2;
69419		if (gcLen > arrayOfThings.length) {
69420			for (var i = 0; i < gcLen; i++) {
69421				delete data[gc[i]];
69422			}
69423			gc.splice(0, gcLen);
69424		}
69425		return longest;
69426	};
69427	helpers$1.measureText = function(ctx, data, gc, longest, string) {
69428		var textWidth = data[string];
69429		if (!textWidth) {
69430			textWidth = data[string] = ctx.measureText(string).width;
69431			gc.push(string);
69432		}
69433		if (textWidth > longest) {
69434			longest = textWidth;
69435		}
69436		return longest;
69437	};
69438	helpers$1.numberOfLabelLines = function(arrayOfThings) {
69439		var numberOfLines = 1;
69440		helpers$1.each(arrayOfThings, function(thing) {
69441			if (helpers$1.isArray(thing)) {
69442				if (thing.length > numberOfLines) {
69443					numberOfLines = thing.length;
69444				}
69445			}
69446		});
69447		return numberOfLines;
69448	};
69449
69450	helpers$1.color = !chartjsColor ?
69451		function(value) {
69452			console.error('Color.js not found!');
69453			return value;
69454		} :
69455		function(value) {
69456			/* global CanvasGradient */
69457			if (value instanceof CanvasGradient) {
69458				value = core_defaults.global.defaultColor;
69459			}
69460
69461			return chartjsColor(value);
69462		};
69463
69464	helpers$1.getHoverColor = function(colorValue) {
69465		/* global CanvasPattern */
69466		return (colorValue instanceof CanvasPattern || colorValue instanceof CanvasGradient) ?
69467			colorValue :
69468			helpers$1.color(colorValue).saturate(0.5).darken(0.1).rgbString();
69469	};
69470};
69471
69472function abstract() {
69473	throw new Error(
69474		'This method is not implemented: either no adapter can ' +
69475		'be found or an incomplete integration was provided.'
69476	);
69477}
69478
69479/**
69480 * Date adapter (current used by the time scale)
69481 * @namespace Chart._adapters._date
69482 * @memberof Chart._adapters
69483 * @private
69484 */
69485
69486/**
69487 * Currently supported unit string values.
69488 * @typedef {('millisecond'|'second'|'minute'|'hour'|'day'|'week'|'month'|'quarter'|'year')}
69489 * @memberof Chart._adapters._date
69490 * @name Unit
69491 */
69492
69493/**
69494 * @class
69495 */
69496function DateAdapter(options) {
69497	this.options = options || {};
69498}
69499
69500helpers$1.extend(DateAdapter.prototype, /** @lends DateAdapter */ {
69501	/**
69502	 * Returns a map of time formats for the supported formatting units defined
69503	 * in Unit as well as 'datetime' representing a detailed date/time string.
69504	 * @returns {{string: string}}
69505	 */
69506	formats: abstract,
69507
69508	/**
69509	 * Parses the given `value` and return the associated timestamp.
69510	 * @param {any} value - the value to parse (usually comes from the data)
69511	 * @param {string} [format] - the expected data format
69512	 * @returns {(number|null)}
69513	 * @function
69514	 */
69515	parse: abstract,
69516
69517	/**
69518	 * Returns the formatted date in the specified `format` for a given `timestamp`.
69519	 * @param {number} timestamp - the timestamp to format
69520	 * @param {string} format - the date/time token
69521	 * @return {string}
69522	 * @function
69523	 */
69524	format: abstract,
69525
69526	/**
69527	 * Adds the specified `amount` of `unit` to the given `timestamp`.
69528	 * @param {number} timestamp - the input timestamp
69529	 * @param {number} amount - the amount to add
69530	 * @param {Unit} unit - the unit as string
69531	 * @return {number}
69532	 * @function
69533	 */
69534	add: abstract,
69535
69536	/**
69537	 * Returns the number of `unit` between the given timestamps.
69538	 * @param {number} max - the input timestamp (reference)
69539	 * @param {number} min - the timestamp to substract
69540	 * @param {Unit} unit - the unit as string
69541	 * @return {number}
69542	 * @function
69543	 */
69544	diff: abstract,
69545
69546	/**
69547	 * Returns start of `unit` for the given `timestamp`.
69548	 * @param {number} timestamp - the input timestamp
69549	 * @param {Unit} unit - the unit as string
69550	 * @param {number} [weekday] - the ISO day of the week with 1 being Monday
69551	 * and 7 being Sunday (only needed if param *unit* is `isoWeek`).
69552	 * @function
69553	 */
69554	startOf: abstract,
69555
69556	/**
69557	 * Returns end of `unit` for the given `timestamp`.
69558	 * @param {number} timestamp - the input timestamp
69559	 * @param {Unit} unit - the unit as string
69560	 * @function
69561	 */
69562	endOf: abstract,
69563
69564	// DEPRECATIONS
69565
69566	/**
69567	 * Provided for backward compatibility for scale.getValueForPixel(),
69568	 * this method should be overridden only by the moment adapter.
69569	 * @deprecated since version 2.8.0
69570	 * @todo remove at version 3
69571	 * @private
69572	 */
69573	_create: function(value) {
69574		return value;
69575	}
69576});
69577
69578DateAdapter.override = function(members) {
69579	helpers$1.extend(DateAdapter.prototype, members);
69580};
69581
69582var _date = DateAdapter;
69583
69584var core_adapters = {
69585	_date: _date
69586};
69587
69588/**
69589 * Namespace to hold static tick generation functions
69590 * @namespace Chart.Ticks
69591 */
69592var core_ticks = {
69593	/**
69594	 * Namespace to hold formatters for different types of ticks
69595	 * @namespace Chart.Ticks.formatters
69596	 */
69597	formatters: {
69598		/**
69599		 * Formatter for value labels
69600		 * @method Chart.Ticks.formatters.values
69601		 * @param value the value to display
69602		 * @return {string|string[]} the label to display
69603		 */
69604		values: function(value) {
69605			return helpers$1.isArray(value) ? value : '' + value;
69606		},
69607
69608		/**
69609		 * Formatter for linear numeric ticks
69610		 * @method Chart.Ticks.formatters.linear
69611		 * @param tickValue {number} the value to be formatted
69612		 * @param index {number} the position of the tickValue parameter in the ticks array
69613		 * @param ticks {number[]} the list of ticks being converted
69614		 * @return {string} string representation of the tickValue parameter
69615		 */
69616		linear: function(tickValue, index, ticks) {
69617			// If we have lots of ticks, don't use the ones
69618			var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
69619
69620			// If we have a number like 2.5 as the delta, figure out how many decimal places we need
69621			if (Math.abs(delta) > 1) {
69622				if (tickValue !== Math.floor(tickValue)) {
69623					// not an integer
69624					delta = tickValue - Math.floor(tickValue);
69625				}
69626			}
69627
69628			var logDelta = helpers$1.log10(Math.abs(delta));
69629			var tickString = '';
69630
69631			if (tickValue !== 0) {
69632				var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1]));
69633				if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation
69634					var logTick = helpers$1.log10(Math.abs(tickValue));
69635					tickString = tickValue.toExponential(Math.floor(logTick) - Math.floor(logDelta));
69636				} else {
69637					var numDecimal = -1 * Math.floor(logDelta);
69638					numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
69639					tickString = tickValue.toFixed(numDecimal);
69640				}
69641			} else {
69642				tickString = '0'; // never show decimal places for 0
69643			}
69644
69645			return tickString;
69646		},
69647
69648		logarithmic: function(tickValue, index, ticks) {
69649			var remain = tickValue / (Math.pow(10, Math.floor(helpers$1.log10(tickValue))));
69650
69651			if (tickValue === 0) {
69652				return '0';
69653			} else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) {
69654				return tickValue.toExponential();
69655			}
69656			return '';
69657		}
69658	}
69659};
69660
69661var valueOrDefault$9 = helpers$1.valueOrDefault;
69662var valueAtIndexOrDefault = helpers$1.valueAtIndexOrDefault;
69663
69664core_defaults._set('scale', {
69665	display: true,
69666	position: 'left',
69667	offset: false,
69668
69669	// grid line settings
69670	gridLines: {
69671		display: true,
69672		color: 'rgba(0, 0, 0, 0.1)',
69673		lineWidth: 1,
69674		drawBorder: true,
69675		drawOnChartArea: true,
69676		drawTicks: true,
69677		tickMarkLength: 10,
69678		zeroLineWidth: 1,
69679		zeroLineColor: 'rgba(0,0,0,0.25)',
69680		zeroLineBorderDash: [],
69681		zeroLineBorderDashOffset: 0.0,
69682		offsetGridLines: false,
69683		borderDash: [],
69684		borderDashOffset: 0.0
69685	},
69686
69687	// scale label
69688	scaleLabel: {
69689		// display property
69690		display: false,
69691
69692		// actual label
69693		labelString: '',
69694
69695		// top/bottom padding
69696		padding: {
69697			top: 4,
69698			bottom: 4
69699		}
69700	},
69701
69702	// label settings
69703	ticks: {
69704		beginAtZero: false,
69705		minRotation: 0,
69706		maxRotation: 50,
69707		mirror: false,
69708		padding: 0,
69709		reverse: false,
69710		display: true,
69711		autoSkip: true,
69712		autoSkipPadding: 0,
69713		labelOffset: 0,
69714		// We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
69715		callback: core_ticks.formatters.values,
69716		minor: {},
69717		major: {}
69718	}
69719});
69720
69721function labelsFromTicks(ticks) {
69722	var labels = [];
69723	var i, ilen;
69724
69725	for (i = 0, ilen = ticks.length; i < ilen; ++i) {
69726		labels.push(ticks[i].label);
69727	}
69728
69729	return labels;
69730}
69731
69732function getPixelForGridLine(scale, index, offsetGridLines) {
69733	var lineValue = scale.getPixelForTick(index);
69734
69735	if (offsetGridLines) {
69736		if (scale.getTicks().length === 1) {
69737			lineValue -= scale.isHorizontal() ?
69738				Math.max(lineValue - scale.left, scale.right - lineValue) :
69739				Math.max(lineValue - scale.top, scale.bottom - lineValue);
69740		} else if (index === 0) {
69741			lineValue -= (scale.getPixelForTick(1) - lineValue) / 2;
69742		} else {
69743			lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2;
69744		}
69745	}
69746	return lineValue;
69747}
69748
69749function computeTextSize(context, tick, font) {
69750	return helpers$1.isArray(tick) ?
69751		helpers$1.longestText(context, font, tick) :
69752		context.measureText(tick).width;
69753}
69754
69755var core_scale = core_element.extend({
69756	/**
69757	 * Get the padding needed for the scale
69758	 * @method getPadding
69759	 * @private
69760	 * @returns {Padding} the necessary padding
69761	 */
69762	getPadding: function() {
69763		var me = this;
69764		return {
69765			left: me.paddingLeft || 0,
69766			top: me.paddingTop || 0,
69767			right: me.paddingRight || 0,
69768			bottom: me.paddingBottom || 0
69769		};
69770	},
69771
69772	/**
69773	 * Returns the scale tick objects ({label, major})
69774	 * @since 2.7
69775	 */
69776	getTicks: function() {
69777		return this._ticks;
69778	},
69779
69780	// These methods are ordered by lifecyle. Utilities then follow.
69781	// Any function defined here is inherited by all scale types.
69782	// Any function can be extended by the scale type
69783
69784	mergeTicksOptions: function() {
69785		var ticks = this.options.ticks;
69786		if (ticks.minor === false) {
69787			ticks.minor = {
69788				display: false
69789			};
69790		}
69791		if (ticks.major === false) {
69792			ticks.major = {
69793				display: false
69794			};
69795		}
69796		for (var key in ticks) {
69797			if (key !== 'major' && key !== 'minor') {
69798				if (typeof ticks.minor[key] === 'undefined') {
69799					ticks.minor[key] = ticks[key];
69800				}
69801				if (typeof ticks.major[key] === 'undefined') {
69802					ticks.major[key] = ticks[key];
69803				}
69804			}
69805		}
69806	},
69807	beforeUpdate: function() {
69808		helpers$1.callback(this.options.beforeUpdate, [this]);
69809	},
69810
69811	update: function(maxWidth, maxHeight, margins) {
69812		var me = this;
69813		var i, ilen, labels, label, ticks, tick;
69814
69815		// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
69816		me.beforeUpdate();
69817
69818		// Absorb the master measurements
69819		me.maxWidth = maxWidth;
69820		me.maxHeight = maxHeight;
69821		me.margins = helpers$1.extend({
69822			left: 0,
69823			right: 0,
69824			top: 0,
69825			bottom: 0
69826		}, margins);
69827
69828		me._maxLabelLines = 0;
69829		me.longestLabelWidth = 0;
69830		me.longestTextCache = me.longestTextCache || {};
69831
69832		// Dimensions
69833		me.beforeSetDimensions();
69834		me.setDimensions();
69835		me.afterSetDimensions();
69836
69837		// Data min/max
69838		me.beforeDataLimits();
69839		me.determineDataLimits();
69840		me.afterDataLimits();
69841
69842		// Ticks - `this.ticks` is now DEPRECATED!
69843		// Internal ticks are now stored as objects in the PRIVATE `this._ticks` member
69844		// and must not be accessed directly from outside this class. `this.ticks` being
69845		// around for long time and not marked as private, we can't change its structure
69846		// without unexpected breaking changes. If you need to access the scale ticks,
69847		// use scale.getTicks() instead.
69848
69849		me.beforeBuildTicks();
69850
69851		// New implementations should return an array of objects but for BACKWARD COMPAT,
69852		// we still support no return (`this.ticks` internally set by calling this method).
69853		ticks = me.buildTicks() || [];
69854
69855		// Allow modification of ticks in callback.
69856		ticks = me.afterBuildTicks(ticks) || ticks;
69857
69858		me.beforeTickToLabelConversion();
69859
69860		// New implementations should return the formatted tick labels but for BACKWARD
69861		// COMPAT, we still support no return (`this.ticks` internally changed by calling
69862		// this method and supposed to contain only string values).
69863		labels = me.convertTicksToLabels(ticks) || me.ticks;
69864
69865		me.afterTickToLabelConversion();
69866
69867		me.ticks = labels;   // BACKWARD COMPATIBILITY
69868
69869		// IMPORTANT: from this point, we consider that `this.ticks` will NEVER change!
69870
69871		// BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`)
69872		for (i = 0, ilen = labels.length; i < ilen; ++i) {
69873			label = labels[i];
69874			tick = ticks[i];
69875			if (!tick) {
69876				ticks.push(tick = {
69877					label: label,
69878					major: false
69879				});
69880			} else {
69881				tick.label = label;
69882			}
69883		}
69884
69885		me._ticks = ticks;
69886
69887		// Tick Rotation
69888		me.beforeCalculateTickRotation();
69889		me.calculateTickRotation();
69890		me.afterCalculateTickRotation();
69891		// Fit
69892		me.beforeFit();
69893		me.fit();
69894		me.afterFit();
69895		//
69896		me.afterUpdate();
69897
69898		return me.minSize;
69899
69900	},
69901	afterUpdate: function() {
69902		helpers$1.callback(this.options.afterUpdate, [this]);
69903	},
69904
69905	//
69906
69907	beforeSetDimensions: function() {
69908		helpers$1.callback(this.options.beforeSetDimensions, [this]);
69909	},
69910	setDimensions: function() {
69911		var me = this;
69912		// Set the unconstrained dimension before label rotation
69913		if (me.isHorizontal()) {
69914			// Reset position before calculating rotation
69915			me.width = me.maxWidth;
69916			me.left = 0;
69917			me.right = me.width;
69918		} else {
69919			me.height = me.maxHeight;
69920
69921			// Reset position before calculating rotation
69922			me.top = 0;
69923			me.bottom = me.height;
69924		}
69925
69926		// Reset padding
69927		me.paddingLeft = 0;
69928		me.paddingTop = 0;
69929		me.paddingRight = 0;
69930		me.paddingBottom = 0;
69931	},
69932	afterSetDimensions: function() {
69933		helpers$1.callback(this.options.afterSetDimensions, [this]);
69934	},
69935
69936	// Data limits
69937	beforeDataLimits: function() {
69938		helpers$1.callback(this.options.beforeDataLimits, [this]);
69939	},
69940	determineDataLimits: helpers$1.noop,
69941	afterDataLimits: function() {
69942		helpers$1.callback(this.options.afterDataLimits, [this]);
69943	},
69944
69945	//
69946	beforeBuildTicks: function() {
69947		helpers$1.callback(this.options.beforeBuildTicks, [this]);
69948	},
69949	buildTicks: helpers$1.noop,
69950	afterBuildTicks: function(ticks) {
69951		var me = this;
69952		// ticks is empty for old axis implementations here
69953		if (helpers$1.isArray(ticks) && ticks.length) {
69954			return helpers$1.callback(me.options.afterBuildTicks, [me, ticks]);
69955		}
69956		// Support old implementations (that modified `this.ticks` directly in buildTicks)
69957		me.ticks = helpers$1.callback(me.options.afterBuildTicks, [me, me.ticks]) || me.ticks;
69958		return ticks;
69959	},
69960
69961	beforeTickToLabelConversion: function() {
69962		helpers$1.callback(this.options.beforeTickToLabelConversion, [this]);
69963	},
69964	convertTicksToLabels: function() {
69965		var me = this;
69966		// Convert ticks to strings
69967		var tickOpts = me.options.ticks;
69968		me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback, this);
69969	},
69970	afterTickToLabelConversion: function() {
69971		helpers$1.callback(this.options.afterTickToLabelConversion, [this]);
69972	},
69973
69974	//
69975
69976	beforeCalculateTickRotation: function() {
69977		helpers$1.callback(this.options.beforeCalculateTickRotation, [this]);
69978	},
69979	calculateTickRotation: function() {
69980		var me = this;
69981		var context = me.ctx;
69982		var tickOpts = me.options.ticks;
69983		var labels = labelsFromTicks(me._ticks);
69984
69985		// Get the width of each grid by calculating the difference
69986		// between x offsets between 0 and 1.
69987		var tickFont = helpers$1.options._parseFont(tickOpts);
69988		context.font = tickFont.string;
69989
69990		var labelRotation = tickOpts.minRotation || 0;
69991
69992		if (labels.length && me.options.display && me.isHorizontal()) {
69993			var originalLabelWidth = helpers$1.longestText(context, tickFont.string, labels, me.longestTextCache);
69994			var labelWidth = originalLabelWidth;
69995			var cosRotation, sinRotation;
69996
69997			// Allow 3 pixels x2 padding either side for label readability
69998			var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6;
69999
70000			// Max label rotation can be set or default to 90 - also act as a loop counter
70001			while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) {
70002				var angleRadians = helpers$1.toRadians(labelRotation);
70003				cosRotation = Math.cos(angleRadians);
70004				sinRotation = Math.sin(angleRadians);
70005
70006				if (sinRotation * originalLabelWidth > me.maxHeight) {
70007					// go back one step
70008					labelRotation--;
70009					break;
70010				}
70011
70012				labelRotation++;
70013				labelWidth = cosRotation * originalLabelWidth;
70014			}
70015		}
70016
70017		me.labelRotation = labelRotation;
70018	},
70019	afterCalculateTickRotation: function() {
70020		helpers$1.callback(this.options.afterCalculateTickRotation, [this]);
70021	},
70022
70023	//
70024
70025	beforeFit: function() {
70026		helpers$1.callback(this.options.beforeFit, [this]);
70027	},
70028	fit: function() {
70029		var me = this;
70030		// Reset
70031		var minSize = me.minSize = {
70032			width: 0,
70033			height: 0
70034		};
70035
70036		var labels = labelsFromTicks(me._ticks);
70037
70038		var opts = me.options;
70039		var tickOpts = opts.ticks;
70040		var scaleLabelOpts = opts.scaleLabel;
70041		var gridLineOpts = opts.gridLines;
70042		var display = me._isVisible();
70043		var position = opts.position;
70044		var isHorizontal = me.isHorizontal();
70045
70046		var parseFont = helpers$1.options._parseFont;
70047		var tickFont = parseFont(tickOpts);
70048		var tickMarkLength = opts.gridLines.tickMarkLength;
70049
70050		// Width
70051		if (isHorizontal) {
70052			// subtract the margins to line up with the chartArea if we are a full width scale
70053			minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth;
70054		} else {
70055			minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
70056		}
70057
70058		// height
70059		if (isHorizontal) {
70060			minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
70061		} else {
70062			minSize.height = me.maxHeight; // fill all the height
70063		}
70064
70065		// Are we showing a title for the scale?
70066		if (scaleLabelOpts.display && display) {
70067			var scaleLabelFont = parseFont(scaleLabelOpts);
70068			var scaleLabelPadding = helpers$1.options.toPadding(scaleLabelOpts.padding);
70069			var deltaHeight = scaleLabelFont.lineHeight + scaleLabelPadding.height;
70070
70071			if (isHorizontal) {
70072				minSize.height += deltaHeight;
70073			} else {
70074				minSize.width += deltaHeight;
70075			}
70076		}
70077
70078		// Don't bother fitting the ticks if we are not showing the labels
70079		if (tickOpts.display && display) {
70080			var largestTextWidth = helpers$1.longestText(me.ctx, tickFont.string, labels, me.longestTextCache);
70081			var tallestLabelHeightInLines = helpers$1.numberOfLabelLines(labels);
70082			var lineSpace = tickFont.size * 0.5;
70083			var tickPadding = me.options.ticks.padding;
70084
70085			// Store max number of lines and widest label for _autoSkip
70086			me._maxLabelLines = tallestLabelHeightInLines;
70087			me.longestLabelWidth = largestTextWidth;
70088
70089			if (isHorizontal) {
70090				var angleRadians = helpers$1.toRadians(me.labelRotation);
70091				var cosRotation = Math.cos(angleRadians);
70092				var sinRotation = Math.sin(angleRadians);
70093
70094				// TODO - improve this calculation
70095				var labelHeight = (sinRotation * largestTextWidth)
70096					+ (tickFont.lineHeight * tallestLabelHeightInLines)
70097					+ lineSpace; // padding
70098
70099				minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding);
70100
70101				me.ctx.font = tickFont.string;
70102				var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.string);
70103				var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.string);
70104				var offsetLeft = me.getPixelForTick(0) - me.left;
70105				var offsetRight = me.right - me.getPixelForTick(labels.length - 1);
70106				var paddingLeft, paddingRight;
70107
70108				// Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
70109				// which means that the right padding is dominated by the font height
70110				if (me.labelRotation !== 0) {
70111					paddingLeft = position === 'bottom' ? (cosRotation * firstLabelWidth) : (cosRotation * lineSpace);
70112					paddingRight = position === 'bottom' ? (cosRotation * lineSpace) : (cosRotation * lastLabelWidth);
70113				} else {
70114					paddingLeft = firstLabelWidth / 2;
70115					paddingRight = lastLabelWidth / 2;
70116				}
70117				me.paddingLeft = Math.max(paddingLeft - offsetLeft, 0) + 3; // add 3 px to move away from canvas edges
70118				me.paddingRight = Math.max(paddingRight - offsetRight, 0) + 3;
70119			} else {
70120				// A vertical axis is more constrained by the width. Labels are the
70121				// dominant factor here, so get that length first and account for padding
70122				if (tickOpts.mirror) {
70123					largestTextWidth = 0;
70124				} else {
70125					// use lineSpace for consistency with horizontal axis
70126					// tickPadding is not implemented for horizontal
70127					largestTextWidth += tickPadding + lineSpace;
70128				}
70129
70130				minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth);
70131
70132				me.paddingTop = tickFont.size / 2;
70133				me.paddingBottom = tickFont.size / 2;
70134			}
70135		}
70136
70137		me.handleMargins();
70138
70139		me.width = minSize.width;
70140		me.height = minSize.height;
70141	},
70142
70143	/**
70144	 * Handle margins and padding interactions
70145	 * @private
70146	 */
70147	handleMargins: function() {
70148		var me = this;
70149		if (me.margins) {
70150			me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
70151			me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0);
70152			me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
70153			me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0);
70154		}
70155	},
70156
70157	afterFit: function() {
70158		helpers$1.callback(this.options.afterFit, [this]);
70159	},
70160
70161	// Shared Methods
70162	isHorizontal: function() {
70163		return this.options.position === 'top' || this.options.position === 'bottom';
70164	},
70165	isFullWidth: function() {
70166		return (this.options.fullWidth);
70167	},
70168
70169	// Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
70170	getRightValue: function(rawValue) {
70171		// Null and undefined values first
70172		if (helpers$1.isNullOrUndef(rawValue)) {
70173			return NaN;
70174		}
70175		// isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values
70176		if ((typeof rawValue === 'number' || rawValue instanceof Number) && !isFinite(rawValue)) {
70177			return NaN;
70178		}
70179		// If it is in fact an object, dive in one more level
70180		if (rawValue) {
70181			if (this.isHorizontal()) {
70182				if (rawValue.x !== undefined) {
70183					return this.getRightValue(rawValue.x);
70184				}
70185			} else if (rawValue.y !== undefined) {
70186				return this.getRightValue(rawValue.y);
70187			}
70188		}
70189
70190		// Value is good, return it
70191		return rawValue;
70192	},
70193
70194	/**
70195	 * Used to get the value to display in the tooltip for the data at the given index
70196	 * @param index
70197	 * @param datasetIndex
70198	 */
70199	getLabelForIndex: helpers$1.noop,
70200
70201	/**
70202	 * Returns the location of the given data point. Value can either be an index or a numerical value
70203	 * The coordinate (0, 0) is at the upper-left corner of the canvas
70204	 * @param value
70205	 * @param index
70206	 * @param datasetIndex
70207	 */
70208	getPixelForValue: helpers$1.noop,
70209
70210	/**
70211	 * Used to get the data value from a given pixel. This is the inverse of getPixelForValue
70212	 * The coordinate (0, 0) is at the upper-left corner of the canvas
70213	 * @param pixel
70214	 */
70215	getValueForPixel: helpers$1.noop,
70216
70217	/**
70218	 * Returns the location of the tick at the given index
70219	 * The coordinate (0, 0) is at the upper-left corner of the canvas
70220	 */
70221	getPixelForTick: function(index) {
70222		var me = this;
70223		var offset = me.options.offset;
70224		if (me.isHorizontal()) {
70225			var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
70226			var tickWidth = innerWidth / Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
70227			var pixel = (tickWidth * index) + me.paddingLeft;
70228
70229			if (offset) {
70230				pixel += tickWidth / 2;
70231			}
70232
70233			var finalVal = me.left + pixel;
70234			finalVal += me.isFullWidth() ? me.margins.left : 0;
70235			return finalVal;
70236		}
70237		var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
70238		return me.top + (index * (innerHeight / (me._ticks.length - 1)));
70239	},
70240
70241	/**
70242	 * Utility for getting the pixel location of a percentage of scale
70243	 * The coordinate (0, 0) is at the upper-left corner of the canvas
70244	 */
70245	getPixelForDecimal: function(decimal) {
70246		var me = this;
70247		if (me.isHorizontal()) {
70248			var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
70249			var valueOffset = (innerWidth * decimal) + me.paddingLeft;
70250
70251			var finalVal = me.left + valueOffset;
70252			finalVal += me.isFullWidth() ? me.margins.left : 0;
70253			return finalVal;
70254		}
70255		return me.top + (decimal * me.height);
70256	},
70257
70258	/**
70259	 * Returns the pixel for the minimum chart value
70260	 * The coordinate (0, 0) is at the upper-left corner of the canvas
70261	 */
70262	getBasePixel: function() {
70263		return this.getPixelForValue(this.getBaseValue());
70264	},
70265
70266	getBaseValue: function() {
70267		var me = this;
70268		var min = me.min;
70269		var max = me.max;
70270
70271		return me.beginAtZero ? 0 :
70272			min < 0 && max < 0 ? max :
70273			min > 0 && max > 0 ? min :
70274			0;
70275	},
70276
70277	/**
70278	 * Returns a subset of ticks to be plotted to avoid overlapping labels.
70279	 * @private
70280	 */
70281	_autoSkip: function(ticks) {
70282		var me = this;
70283		var isHorizontal = me.isHorizontal();
70284		var optionTicks = me.options.ticks.minor;
70285		var tickCount = ticks.length;
70286		var skipRatio = false;
70287		var maxTicks = optionTicks.maxTicksLimit;
70288
70289		// Total space needed to display all ticks. First and last ticks are
70290		// drawn as their center at end of axis, so tickCount-1
70291		var ticksLength = me._tickSize() * (tickCount - 1);
70292
70293		// Axis length
70294		var axisLength = isHorizontal
70295			? me.width - (me.paddingLeft + me.paddingRight)
70296			: me.height - (me.paddingTop + me.PaddingBottom);
70297
70298		var result = [];
70299		var i, tick;
70300
70301		if (ticksLength > axisLength) {
70302			skipRatio = 1 + Math.floor(ticksLength / axisLength);
70303		}
70304
70305		// if they defined a max number of optionTicks,
70306		// increase skipRatio until that number is met
70307		if (tickCount > maxTicks) {
70308			skipRatio = Math.max(skipRatio, 1 + Math.floor(tickCount / maxTicks));
70309		}
70310
70311		for (i = 0; i < tickCount; i++) {
70312			tick = ticks[i];
70313
70314			if (skipRatio > 1 && i % skipRatio > 0) {
70315				// leave tick in place but make sure it's not displayed (#4635)
70316				delete tick.label;
70317			}
70318			result.push(tick);
70319		}
70320		return result;
70321	},
70322
70323	/**
70324	 * @private
70325	 */
70326	_tickSize: function() {
70327		var me = this;
70328		var isHorizontal = me.isHorizontal();
70329		var optionTicks = me.options.ticks.minor;
70330
70331		// Calculate space needed by label in axis direction.
70332		var rot = helpers$1.toRadians(me.labelRotation);
70333		var cos = Math.abs(Math.cos(rot));
70334		var sin = Math.abs(Math.sin(rot));
70335
70336		var padding = optionTicks.autoSkipPadding || 0;
70337		var w = (me.longestLabelWidth + padding) || 0;
70338
70339		var tickFont = helpers$1.options._parseFont(optionTicks);
70340		var h = (me._maxLabelLines * tickFont.lineHeight + padding) || 0;
70341
70342		// Calculate space needed for 1 tick in axis direction.
70343		return isHorizontal
70344			? h * cos > w * sin ? w / cos : h / sin
70345			: h * sin < w * cos ? h / cos : w / sin;
70346	},
70347
70348	/**
70349	 * @private
70350	 */
70351	_isVisible: function() {
70352		var me = this;
70353		var chart = me.chart;
70354		var display = me.options.display;
70355		var i, ilen, meta;
70356
70357		if (display !== 'auto') {
70358			return !!display;
70359		}
70360
70361		// When 'auto', the scale is visible if at least one associated dataset is visible.
70362		for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
70363			if (chart.isDatasetVisible(i)) {
70364				meta = chart.getDatasetMeta(i);
70365				if (meta.xAxisID === me.id || meta.yAxisID === me.id) {
70366					return true;
70367				}
70368			}
70369		}
70370
70371		return false;
70372	},
70373
70374	/**
70375	 * Actually draw the scale on the canvas
70376	 * @param {object} chartArea - the area of the chart to draw full grid lines on
70377	 */
70378	draw: function(chartArea) {
70379		var me = this;
70380		var options = me.options;
70381
70382		if (!me._isVisible()) {
70383			return;
70384		}
70385
70386		var chart = me.chart;
70387		var context = me.ctx;
70388		var globalDefaults = core_defaults.global;
70389		var defaultFontColor = globalDefaults.defaultFontColor;
70390		var optionTicks = options.ticks.minor;
70391		var optionMajorTicks = options.ticks.major || optionTicks;
70392		var gridLines = options.gridLines;
70393		var scaleLabel = options.scaleLabel;
70394		var position = options.position;
70395
70396		var isRotated = me.labelRotation !== 0;
70397		var isMirrored = optionTicks.mirror;
70398		var isHorizontal = me.isHorizontal();
70399
70400		var parseFont = helpers$1.options._parseFont;
70401		var ticks = optionTicks.display && optionTicks.autoSkip ? me._autoSkip(me.getTicks()) : me.getTicks();
70402		var tickFontColor = valueOrDefault$9(optionTicks.fontColor, defaultFontColor);
70403		var tickFont = parseFont(optionTicks);
70404		var lineHeight = tickFont.lineHeight;
70405		var majorTickFontColor = valueOrDefault$9(optionMajorTicks.fontColor, defaultFontColor);
70406		var majorTickFont = parseFont(optionMajorTicks);
70407		var tickPadding = optionTicks.padding;
70408		var labelOffset = optionTicks.labelOffset;
70409
70410		var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0;
70411
70412		var scaleLabelFontColor = valueOrDefault$9(scaleLabel.fontColor, defaultFontColor);
70413		var scaleLabelFont = parseFont(scaleLabel);
70414		var scaleLabelPadding = helpers$1.options.toPadding(scaleLabel.padding);
70415		var labelRotationRadians = helpers$1.toRadians(me.labelRotation);
70416
70417		var itemsToDraw = [];
70418
70419		var axisWidth = gridLines.drawBorder ? valueAtIndexOrDefault(gridLines.lineWidth, 0, 0) : 0;
70420		var alignPixel = helpers$1._alignPixel;
70421		var borderValue, tickStart, tickEnd;
70422
70423		if (position === 'top') {
70424			borderValue = alignPixel(chart, me.bottom, axisWidth);
70425			tickStart = me.bottom - tl;
70426			tickEnd = borderValue - axisWidth / 2;
70427		} else if (position === 'bottom') {
70428			borderValue = alignPixel(chart, me.top, axisWidth);
70429			tickStart = borderValue + axisWidth / 2;
70430			tickEnd = me.top + tl;
70431		} else if (position === 'left') {
70432			borderValue = alignPixel(chart, me.right, axisWidth);
70433			tickStart = me.right - tl;
70434			tickEnd = borderValue - axisWidth / 2;
70435		} else {
70436			borderValue = alignPixel(chart, me.left, axisWidth);
70437			tickStart = borderValue + axisWidth / 2;
70438			tickEnd = me.left + tl;
70439		}
70440
70441		var epsilon = 0.0000001; // 0.0000001 is margin in pixels for Accumulated error.
70442
70443		helpers$1.each(ticks, function(tick, index) {
70444			// autoskipper skipped this tick (#4635)
70445			if (helpers$1.isNullOrUndef(tick.label)) {
70446				return;
70447			}
70448
70449			var label = tick.label;
70450			var lineWidth, lineColor, borderDash, borderDashOffset;
70451			if (index === me.zeroLineIndex && options.offset === gridLines.offsetGridLines) {
70452				// Draw the first index specially
70453				lineWidth = gridLines.zeroLineWidth;
70454				lineColor = gridLines.zeroLineColor;
70455				borderDash = gridLines.zeroLineBorderDash || [];
70456				borderDashOffset = gridLines.zeroLineBorderDashOffset || 0.0;
70457			} else {
70458				lineWidth = valueAtIndexOrDefault(gridLines.lineWidth, index);
70459				lineColor = valueAtIndexOrDefault(gridLines.color, index);
70460				borderDash = gridLines.borderDash || [];
70461				borderDashOffset = gridLines.borderDashOffset || 0.0;
70462			}
70463
70464			// Common properties
70465			var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY, textOffset, textAlign;
70466			var labelCount = helpers$1.isArray(label) ? label.length : 1;
70467			var lineValue = getPixelForGridLine(me, index, gridLines.offsetGridLines);
70468
70469			if (isHorizontal) {
70470				var labelYOffset = tl + tickPadding;
70471
70472				if (lineValue < me.left - epsilon) {
70473					lineColor = 'rgba(0,0,0,0)';
70474				}
70475
70476				tx1 = tx2 = x1 = x2 = alignPixel(chart, lineValue, lineWidth);
70477				ty1 = tickStart;
70478				ty2 = tickEnd;
70479				labelX = me.getPixelForTick(index) + labelOffset; // x values for optionTicks (need to consider offsetLabel option)
70480
70481				if (position === 'top') {
70482					y1 = alignPixel(chart, chartArea.top, axisWidth) + axisWidth / 2;
70483					y2 = chartArea.bottom;
70484					textOffset = ((!isRotated ? 0.5 : 1) - labelCount) * lineHeight;
70485					textAlign = !isRotated ? 'center' : 'left';
70486					labelY = me.bottom - labelYOffset;
70487				} else {
70488					y1 = chartArea.top;
70489					y2 = alignPixel(chart, chartArea.bottom, axisWidth) - axisWidth / 2;
70490					textOffset = (!isRotated ? 0.5 : 0) * lineHeight;
70491					textAlign = !isRotated ? 'center' : 'right';
70492					labelY = me.top + labelYOffset;
70493				}
70494			} else {
70495				var labelXOffset = (isMirrored ? 0 : tl) + tickPadding;
70496
70497				if (lineValue < me.top - epsilon) {
70498					lineColor = 'rgba(0,0,0,0)';
70499				}
70500
70501				tx1 = tickStart;
70502				tx2 = tickEnd;
70503				ty1 = ty2 = y1 = y2 = alignPixel(chart, lineValue, lineWidth);
70504				labelY = me.getPixelForTick(index) + labelOffset;
70505				textOffset = (1 - labelCount) * lineHeight / 2;
70506
70507				if (position === 'left') {
70508					x1 = alignPixel(chart, chartArea.left, axisWidth) + axisWidth / 2;
70509					x2 = chartArea.right;
70510					textAlign = isMirrored ? 'left' : 'right';
70511					labelX = me.right - labelXOffset;
70512				} else {
70513					x1 = chartArea.left;
70514					x2 = alignPixel(chart, chartArea.right, axisWidth) - axisWidth / 2;
70515					textAlign = isMirrored ? 'right' : 'left';
70516					labelX = me.left + labelXOffset;
70517				}
70518			}
70519
70520			itemsToDraw.push({
70521				tx1: tx1,
70522				ty1: ty1,
70523				tx2: tx2,
70524				ty2: ty2,
70525				x1: x1,
70526				y1: y1,
70527				x2: x2,
70528				y2: y2,
70529				labelX: labelX,
70530				labelY: labelY,
70531				glWidth: lineWidth,
70532				glColor: lineColor,
70533				glBorderDash: borderDash,
70534				glBorderDashOffset: borderDashOffset,
70535				rotation: -1 * labelRotationRadians,
70536				label: label,
70537				major: tick.major,
70538				textOffset: textOffset,
70539				textAlign: textAlign
70540			});
70541		});
70542
70543		// Draw all of the tick labels, tick marks, and grid lines at the correct places
70544		helpers$1.each(itemsToDraw, function(itemToDraw) {
70545			var glWidth = itemToDraw.glWidth;
70546			var glColor = itemToDraw.glColor;
70547
70548			if (gridLines.display && glWidth && glColor) {
70549				context.save();
70550				context.lineWidth = glWidth;
70551				context.strokeStyle = glColor;
70552				if (context.setLineDash) {
70553					context.setLineDash(itemToDraw.glBorderDash);
70554					context.lineDashOffset = itemToDraw.glBorderDashOffset;
70555				}
70556
70557				context.beginPath();
70558
70559				if (gridLines.drawTicks) {
70560					context.moveTo(itemToDraw.tx1, itemToDraw.ty1);
70561					context.lineTo(itemToDraw.tx2, itemToDraw.ty2);
70562				}
70563
70564				if (gridLines.drawOnChartArea) {
70565					context.moveTo(itemToDraw.x1, itemToDraw.y1);
70566					context.lineTo(itemToDraw.x2, itemToDraw.y2);
70567				}
70568
70569				context.stroke();
70570				context.restore();
70571			}
70572
70573			if (optionTicks.display) {
70574				// Make sure we draw text in the correct color and font
70575				context.save();
70576				context.translate(itemToDraw.labelX, itemToDraw.labelY);
70577				context.rotate(itemToDraw.rotation);
70578				context.font = itemToDraw.major ? majorTickFont.string : tickFont.string;
70579				context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor;
70580				context.textBaseline = 'middle';
70581				context.textAlign = itemToDraw.textAlign;
70582
70583				var label = itemToDraw.label;
70584				var y = itemToDraw.textOffset;
70585				if (helpers$1.isArray(label)) {
70586					for (var i = 0; i < label.length; ++i) {
70587						// We just make sure the multiline element is a string here..
70588						context.fillText('' + label[i], 0, y);
70589						y += lineHeight;
70590					}
70591				} else {
70592					context.fillText(label, 0, y);
70593				}
70594				context.restore();
70595			}
70596		});
70597
70598		if (scaleLabel.display) {
70599			// Draw the scale label
70600			var scaleLabelX;
70601			var scaleLabelY;
70602			var rotation = 0;
70603			var halfLineHeight = scaleLabelFont.lineHeight / 2;
70604
70605			if (isHorizontal) {
70606				scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
70607				scaleLabelY = position === 'bottom'
70608					? me.bottom - halfLineHeight - scaleLabelPadding.bottom
70609					: me.top + halfLineHeight + scaleLabelPadding.top;
70610			} else {
70611				var isLeft = position === 'left';
70612				scaleLabelX = isLeft
70613					? me.left + halfLineHeight + scaleLabelPadding.top
70614					: me.right - halfLineHeight - scaleLabelPadding.top;
70615				scaleLabelY = me.top + ((me.bottom - me.top) / 2);
70616				rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
70617			}
70618
70619			context.save();
70620			context.translate(scaleLabelX, scaleLabelY);
70621			context.rotate(rotation);
70622			context.textAlign = 'center';
70623			context.textBaseline = 'middle';
70624			context.fillStyle = scaleLabelFontColor; // render in correct colour
70625			context.font = scaleLabelFont.string;
70626			context.fillText(scaleLabel.labelString, 0, 0);
70627			context.restore();
70628		}
70629
70630		if (axisWidth) {
70631			// Draw the line at the edge of the axis
70632			var firstLineWidth = axisWidth;
70633			var lastLineWidth = valueAtIndexOrDefault(gridLines.lineWidth, ticks.length - 1, 0);
70634			var x1, x2, y1, y2;
70635
70636			if (isHorizontal) {
70637				x1 = alignPixel(chart, me.left, firstLineWidth) - firstLineWidth / 2;
70638				x2 = alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2;
70639				y1 = y2 = borderValue;
70640			} else {
70641				y1 = alignPixel(chart, me.top, firstLineWidth) - firstLineWidth / 2;
70642				y2 = alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2;
70643				x1 = x2 = borderValue;
70644			}
70645
70646			context.lineWidth = axisWidth;
70647			context.strokeStyle = valueAtIndexOrDefault(gridLines.color, 0);
70648			context.beginPath();
70649			context.moveTo(x1, y1);
70650			context.lineTo(x2, y2);
70651			context.stroke();
70652		}
70653	}
70654});
70655
70656var defaultConfig = {
70657	position: 'bottom'
70658};
70659
70660var scale_category = core_scale.extend({
70661	/**
70662	* Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those
70663	* else fall back to data.labels
70664	* @private
70665	*/
70666	getLabels: function() {
70667		var data = this.chart.data;
70668		return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels;
70669	},
70670
70671	determineDataLimits: function() {
70672		var me = this;
70673		var labels = me.getLabels();
70674		me.minIndex = 0;
70675		me.maxIndex = labels.length - 1;
70676		var findIndex;
70677
70678		if (me.options.ticks.min !== undefined) {
70679			// user specified min value
70680			findIndex = labels.indexOf(me.options.ticks.min);
70681			me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
70682		}
70683
70684		if (me.options.ticks.max !== undefined) {
70685			// user specified max value
70686			findIndex = labels.indexOf(me.options.ticks.max);
70687			me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
70688		}
70689
70690		me.min = labels[me.minIndex];
70691		me.max = labels[me.maxIndex];
70692	},
70693
70694	buildTicks: function() {
70695		var me = this;
70696		var labels = me.getLabels();
70697		// If we are viewing some subset of labels, slice the original array
70698		me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1);
70699	},
70700
70701	getLabelForIndex: function(index, datasetIndex) {
70702		var me = this;
70703		var chart = me.chart;
70704
70705		if (chart.getDatasetMeta(datasetIndex).controller._getValueScaleId() === me.id) {
70706			return me.getRightValue(chart.data.datasets[datasetIndex].data[index]);
70707		}
70708
70709		return me.ticks[index - me.minIndex];
70710	},
70711
70712	// Used to get data value locations.  Value can either be an index or a numerical value
70713	getPixelForValue: function(value, index) {
70714		var me = this;
70715		var offset = me.options.offset;
70716		// 1 is added because we need the length but we have the indexes
70717		var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1);
70718
70719		// If value is a data object, then index is the index in the data array,
70720		// not the index of the scale. We need to change that.
70721		var valueCategory;
70722		if (value !== undefined && value !== null) {
70723			valueCategory = me.isHorizontal() ? value.x : value.y;
70724		}
70725		if (valueCategory !== undefined || (value !== undefined && isNaN(index))) {
70726			var labels = me.getLabels();
70727			value = valueCategory || value;
70728			var idx = labels.indexOf(value);
70729			index = idx !== -1 ? idx : index;
70730		}
70731
70732		if (me.isHorizontal()) {
70733			var valueWidth = me.width / offsetAmt;
70734			var widthOffset = (valueWidth * (index - me.minIndex));
70735
70736			if (offset) {
70737				widthOffset += (valueWidth / 2);
70738			}
70739
70740			return me.left + widthOffset;
70741		}
70742		var valueHeight = me.height / offsetAmt;
70743		var heightOffset = (valueHeight * (index - me.minIndex));
70744
70745		if (offset) {
70746			heightOffset += (valueHeight / 2);
70747		}
70748
70749		return me.top + heightOffset;
70750	},
70751
70752	getPixelForTick: function(index) {
70753		return this.getPixelForValue(this.ticks[index], index + this.minIndex, null);
70754	},
70755
70756	getValueForPixel: function(pixel) {
70757		var me = this;
70758		var offset = me.options.offset;
70759		var value;
70760		var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
70761		var horz = me.isHorizontal();
70762		var valueDimension = (horz ? me.width : me.height) / offsetAmt;
70763
70764		pixel -= horz ? me.left : me.top;
70765
70766		if (offset) {
70767			pixel -= (valueDimension / 2);
70768		}
70769
70770		if (pixel <= 0) {
70771			value = 0;
70772		} else {
70773			value = Math.round(pixel / valueDimension);
70774		}
70775
70776		return value + me.minIndex;
70777	},
70778
70779	getBasePixel: function() {
70780		return this.bottom;
70781	}
70782});
70783
70784// INTERNAL: static default options, registered in src/index.js
70785var _defaults = defaultConfig;
70786scale_category._defaults = _defaults;
70787
70788var noop = helpers$1.noop;
70789var isNullOrUndef = helpers$1.isNullOrUndef;
70790
70791/**
70792 * Generate a set of linear ticks
70793 * @param generationOptions the options used to generate the ticks
70794 * @param dataRange the range of the data
70795 * @returns {number[]} array of tick values
70796 */
70797function generateTicks(generationOptions, dataRange) {
70798	var ticks = [];
70799	// To get a "nice" value for the tick spacing, we will use the appropriately named
70800	// "nice number" algorithm. See https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
70801	// for details.
70802
70803	var MIN_SPACING = 1e-14;
70804	var stepSize = generationOptions.stepSize;
70805	var unit = stepSize || 1;
vendor: 5,384 bytes, lines 70806-70987
70806	var maxNumSpaces = generationOptions.maxTicks - 1;
70807	var min = generationOptions.min;
70808	var max = generationOptions.max;
70809	var precision = generationOptions.precision;
70810	var rmin = dataRange.min;
70811	var rmax = dataRange.max;
70812	var spacing = helpers$1.niceNum((rmax - rmin) / maxNumSpaces / unit) * unit;
70813	var factor, niceMin, niceMax, numSpaces;
70814
70815	// Beyond MIN_SPACING floating point numbers being to lose precision
70816	// such that we can't do the math necessary to generate ticks
70817	if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) {
70818		return [rmin, rmax];
70819	}
70820
70821	numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
70822	if (numSpaces > maxNumSpaces) {
70823		// If the calculated num of spaces exceeds maxNumSpaces, recalculate it
70824		spacing = helpers$1.niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit;
70825	}
70826
70827	if (stepSize || isNullOrUndef(precision)) {
70828		// If a precision is not specified, calculate factor based on spacing
70829		factor = Math.pow(10, helpers$1._decimalPlaces(spacing));
70830	} else {
70831		// If the user specified a precision, round to that number of decimal places
70832		factor = Math.pow(10, precision);
70833		spacing = Math.ceil(spacing * factor) / factor;
70834	}
70835
70836	niceMin = Math.floor(rmin / spacing) * spacing;
70837	niceMax = Math.ceil(rmax / spacing) * spacing;
70838
70839	// If min, max and stepSize is set and they make an evenly spaced scale use it.
70840	if (stepSize) {
70841		// If very close to our whole number, use it.
70842		if (!isNullOrUndef(min) && helpers$1.almostWhole(min / spacing, spacing / 1000)) {
70843			niceMin = min;
70844		}
70845		if (!isNullOrUndef(max) && helpers$1.almostWhole(max / spacing, spacing / 1000)) {
70846			niceMax = max;
70847		}
70848	}
70849
70850	numSpaces = (niceMax - niceMin) / spacing;
70851	// If very close to our rounded value, use it.
70852	if (helpers$1.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
70853		numSpaces = Math.round(numSpaces);
70854	} else {
70855		numSpaces = Math.ceil(numSpaces);
70856	}
70857
70858	niceMin = Math.round(niceMin * factor) / factor;
70859	niceMax = Math.round(niceMax * factor) / factor;
70860	ticks.push(isNullOrUndef(min) ? niceMin : min);
70861	for (var j = 1; j < numSpaces; ++j) {
70862		ticks.push(Math.round((niceMin + j * spacing) * factor) / factor);
70863	}
70864	ticks.push(isNullOrUndef(max) ? niceMax : max);
70865
70866	return ticks;
70867}
70868
70869var scale_linearbase = core_scale.extend({
70870	getRightValue: function(value) {
70871		if (typeof value === 'string') {
70872			return +value;
70873		}
70874		return core_scale.prototype.getRightValue.call(this, value);
70875	},
70876
70877	handleTickRangeOptions: function() {
70878		var me = this;
70879		var opts = me.options;
70880		var tickOpts = opts.ticks;
70881
70882		// If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
70883		// do nothing since that would make the chart weird. If the user really wants a weird chart
70884		// axis, they can manually override it
70885		if (tickOpts.beginAtZero) {
70886			var minSign = helpers$1.sign(me.min);
70887			var maxSign = helpers$1.sign(me.max);
70888
70889			if (minSign < 0 && maxSign < 0) {
70890				// move the top up to 0
70891				me.max = 0;
70892			} else if (minSign > 0 && maxSign > 0) {
70893				// move the bottom down to 0
70894				me.min = 0;
70895			}
70896		}
70897
70898		var setMin = tickOpts.min !== undefined || tickOpts.suggestedMin !== undefined;
70899		var setMax = tickOpts.max !== undefined || tickOpts.suggestedMax !== undefined;
70900
70901		if (tickOpts.min !== undefined) {
70902			me.min = tickOpts.min;
70903		} else if (tickOpts.suggestedMin !== undefined) {
70904			if (me.min === null) {
70905				me.min = tickOpts.suggestedMin;
70906			} else {
70907				me.min = Math.min(me.min, tickOpts.suggestedMin);
70908			}
70909		}
70910
70911		if (tickOpts.max !== undefined) {
70912			me.max = tickOpts.max;
70913		} else if (tickOpts.suggestedMax !== undefined) {
70914			if (me.max === null) {
70915				me.max = tickOpts.suggestedMax;
70916			} else {
70917				me.max = Math.max(me.max, tickOpts.suggestedMax);
70918			}
70919		}
70920
70921		if (setMin !== setMax) {
70922			// We set the min or the max but not both.
70923			// So ensure that our range is good
70924			// Inverted or 0 length range can happen when
70925			// ticks.min is set, and no datasets are visible
70926			if (me.min >= me.max) {
70927				if (setMin) {
70928					me.max = me.min + 1;
70929				} else {
70930					me.min = me.max - 1;
70931				}
70932			}
70933		}
70934
70935		if (me.min === me.max) {
70936			me.max++;
70937
70938			if (!tickOpts.beginAtZero) {
70939				me.min--;
70940			}
70941		}
70942	},
70943
70944	getTickLimit: function() {
70945		var me = this;
70946		var tickOpts = me.options.ticks;
70947		var stepSize = tickOpts.stepSize;
70948		var maxTicksLimit = tickOpts.maxTicksLimit;
70949		var maxTicks;
70950
70951		if (stepSize) {
70952			maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1;
70953		} else {
70954			maxTicks = me._computeTickLimit();
70955			maxTicksLimit = maxTicksLimit || 11;
70956		}
70957
70958		if (maxTicksLimit) {
70959			maxTicks = Math.min(maxTicksLimit, maxTicks);
70960		}
70961
70962		return maxTicks;
70963	},
70964
70965	_computeTickLimit: function() {
70966		return Number.POSITIVE_INFINITY;
70967	},
70968
70969	handleDirectionalChanges: noop,
70970
70971	buildTicks: function() {
70972		var me = this;
70973		var opts = me.options;
70974		var tickOpts = opts.ticks;
70975
70976		// Figure out what the max number of ticks we can support it is based on the size of
70977		// the axis area. For now, we say that the minimum tick spacing in pixels must be 40
70978		// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
70979		// the graph. Make sure we always have at least 2 ticks
70980		var maxTicks = me.getTickLimit();
70981		maxTicks = Math.max(2, maxTicks);
70982
70983		var numericGeneratorOptions = {
70984			maxTicks: maxTicks,
70985			min: tickOpts.min,
70986			max: tickOpts.max,
70987			precision: tickOpts.precision,
70988			stepSize: helpers$1.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize)
70989		};
70990		var ticks = me.ticks = generateTicks(numericGeneratorOptions, me);
70991
70992		me.handleDirectionalChanges();
70993
70994		// At this point, we need to update our max and min given the tick values since we have expanded the
70995		// range of the scale
70996		me.max = helpers$1.max(ticks);
70997		me.min = helpers$1.min(ticks);
70998
70999		if (tickOpts.reverse) {
71000			ticks.reverse();
71001
71002			me.start = me.max;
71003			me.end = me.min;
71004		} else {
71005			me.start = me.min;
71006			me.end = me.max;
71007		}
71008	},
71009
71010	convertTicksToLabels: function() {
71011		var me = this;
71012		me.ticksAsNumbers = me.ticks.slice();
71013		me.zeroLineIndex = me.ticks.indexOf(0);
71014
71015		core_scale.prototype.convertTicksToLabels.call(me);
71016	}
71017});
71018
71019var defaultConfig$1 = {
71020	position: 'left',
71021	ticks: {
71022		callback: core_ticks.formatters.linear
71023	}
71024};
71025
71026var scale_linear = scale_linearbase.extend({
71027	determineDataLimits: function() {
71028		var me = this;
71029		var opts = me.options;
71030		var chart = me.chart;
71031		var data = chart.data;
71032		var datasets = data.datasets;
71033		var isHorizontal = me.isHorizontal();
71034		var DEFAULT_MIN = 0;
71035		var DEFAULT_MAX = 1;
71036
71037		function IDMatches(meta) {
71038			return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
71039		}
71040
71041		// First Calculate the range
71042		me.min = null;
71043		me.max = null;
71044
71045		var hasStacks = opts.stacked;
71046		if (hasStacks === undefined) {
71047			helpers$1.each(datasets, function(dataset, datasetIndex) {
71048				if (hasStacks) {
71049					return;
71050				}
71051
71052				var meta = chart.getDatasetMeta(datasetIndex);
71053				if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
71054					meta.stack !== undefined) {
71055					hasStacks = true;
71056				}
71057			});
71058		}
71059
71060		if (opts.stacked || hasStacks) {
71061			var valuesPerStack = {};
71062
71063			helpers$1.each(datasets, function(dataset, datasetIndex) {
71064				var meta = chart.getDatasetMeta(datasetIndex);
71065				var key = [
71066					meta.type,
71067					// we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
71068					((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''),
71069					meta.stack
71070				].join('.');
71071
71072				if (valuesPerStack[key] === undefined) {
71073					valuesPerStack[key] = {
71074						positiveValues: [],
71075						negativeValues: []
71076					};
71077				}
71078
71079				// Store these per type
71080				var positiveValues = valuesPerStack[key].positiveValues;
71081				var negativeValues = valuesPerStack[key].negativeValues;
71082
71083				if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
71084					helpers$1.each(dataset.data, function(rawValue, index) {
71085						var value = +me.getRightValue(rawValue);
71086						if (isNaN(value) || meta.data[index].hidden) {
71087							return;
71088						}
71089
71090						positiveValues[index] = positiveValues[index] || 0;
71091						negativeValues[index] = negativeValues[index] || 0;
71092
71093						if (opts.relativePoints) {
71094							positiveValues[index] = 100;
71095						} else if (value < 0) {
71096							negativeValues[index] += value;
71097						} else {
71098							positiveValues[index] += value;
71099						}
71100					});
71101				}
71102			});
71103
71104			helpers$1.each(valuesPerStack, function(valuesForType) {
71105				var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
71106				var minVal = helpers$1.min(values);
71107				var maxVal = helpers$1.max(values);
71108				me.min = me.min === null ? minVal : Math.min(me.min, minVal);
71109				me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
71110			});
71111
71112		} else {
71113			helpers$1.each(datasets, function(dataset, datasetIndex) {
71114				var meta = chart.getDatasetMeta(datasetIndex);
71115				if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
71116					helpers$1.each(dataset.data, function(rawValue, index) {
71117						var value = +me.getRightValue(rawValue);
71118						if (isNaN(value) || meta.data[index].hidden) {
71119							return;
71120						}
71121
71122						if (me.min === null) {
71123							me.min = value;
71124						} else if (value < me.min) {
71125							me.min = value;
71126						}
71127
71128						if (me.max === null) {
71129							me.max = value;
71130						} else if (value > me.max) {
71131							me.max = value;
71132						}
71133					});
71134				}
71135			});
71136		}
71137
71138		me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN;
71139		me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX;
71140
71141		// Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
71142		this.handleTickRangeOptions();
71143	},
71144
71145	// Returns the maximum number of ticks based on the scale dimension
71146	_computeTickLimit: function() {
71147		var me = this;
71148		var tickFont;
71149
71150		if (me.isHorizontal()) {
71151			return Math.ceil(me.width / 40);
71152		}
71153		tickFont = helpers$1.options._parseFont(me.options.ticks);
71154		return Math.ceil(me.height / tickFont.lineHeight);
71155	},
71156
71157	// Called after the ticks are built. We need
71158	handleDirectionalChanges: function() {
71159		if (!this.isHorizontal()) {
71160			// We are in a vertical orientation. The top value is the highest. So reverse the array
71161			this.ticks.reverse();
71162		}
71163	},
71164
71165	getLabelForIndex: function(index, datasetIndex) {
71166		return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
71167	},
71168
71169	// Utils
71170	getPixelForValue: function(value) {
71171		// This must be called after fit has been run so that
71172		// this.left, this.top, this.right, and this.bottom have been defined
71173		var me = this;
71174		var start = me.start;
71175
71176		var rightValue = +me.getRightValue(value);
71177		var pixel;
71178		var range = me.end - start;
71179
71180		if (me.isHorizontal()) {
71181			pixel = me.left + (me.width / range * (rightValue - start));
71182		} else {
71183			pixel = me.bottom - (me.height / range * (rightValue - start));
71184		}
71185		return pixel;
71186	},
71187
71188	getValueForPixel: function(pixel) {
71189		var me = this;
71190		var isHorizontal = me.isHorizontal();
71191		var innerDimension = isHorizontal ? me.width : me.height;
71192		var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension;
71193		return me.start + ((me.end - me.start) * offset);
71194	},
71195
71196	getPixelForTick: function(index) {
71197		return this.getPixelForValue(this.ticksAsNumbers[index]);
71198	}
71199});
71200
71201// INTERNAL: static default options, registered in src/index.js
71202var _defaults$1 = defaultConfig$1;
71203scale_linear._defaults = _defaults$1;
71204
71205var valueOrDefault$a = helpers$1.valueOrDefault;
71206
71207/**
71208 * Generate a set of logarithmic ticks
71209 * @param generationOptions the options used to generate the ticks
71210 * @param dataRange the range of the data
71211 * @returns {number[]} array of tick values
71212 */
71213function generateTicks$1(generationOptions, dataRange) {
71214	var ticks = [];
71215
71216	var tickVal = valueOrDefault$a(generationOptions.min, Math.pow(10, Math.floor(helpers$1.log10(dataRange.min))));
71217
71218	var endExp = Math.floor(helpers$1.log10(dataRange.max));
71219	var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp));
71220	var exp, significand;
71221
71222	if (tickVal === 0) {
71223		exp = Math.floor(helpers$1.log10(dataRange.minNotZero));
71224		significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp));
71225
71226		ticks.push(tickVal);
71227		tickVal = significand * Math.pow(10, exp);
71228	} else {
71229		exp = Math.floor(helpers$1.log10(tickVal));
71230		significand = Math.floor(tickVal / Math.pow(10, exp));
71231	}
71232	var precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;
71233
71234	do {
71235		ticks.push(tickVal);
71236
71237		++significand;
71238		if (significand === 10) {
71239			significand = 1;
71240			++exp;
71241			precision = exp >= 0 ? 1 : precision;
71242		}
71243
71244		tickVal = Math.round(significand * Math.pow(10, exp) * precision) / precision;
71245	} while (exp < endExp || (exp === endExp && significand < endSignificand));
71246
71247	var lastTick = valueOrDefault$a(generationOptions.max, tickVal);
71248	ticks.push(lastTick);
71249
71250	return ticks;
71251}
71252
71253var defaultConfig$2 = {
71254	position: 'left',
71255
71256	// label settings
71257	ticks: {
71258		callback: core_ticks.formatters.logarithmic
71259	}
71260};
71261
71262// TODO(v3): change this to positiveOrDefault
71263function nonNegativeOrDefault(value, defaultValue) {
71264	return helpers$1.isFinite(value) && value >= 0 ? value : defaultValue;
71265}
71266
71267var scale_logarithmic = core_scale.extend({
71268	determineDataLimits: function() {
71269		var me = this;
71270		var opts = me.options;
71271		var chart = me.chart;
71272		var data = chart.data;
71273		var datasets = data.datasets;
71274		var isHorizontal = me.isHorizontal();
71275		function IDMatches(meta) {
71276			return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
71277		}
71278
71279		// Calculate Range
71280		me.min = null;
71281		me.max = null;
71282		me.minNotZero = null;
71283
71284		var hasStacks = opts.stacked;
71285		if (hasStacks === undefined) {
71286			helpers$1.each(datasets, function(dataset, datasetIndex) {
71287				if (hasStacks) {
71288					return;
71289				}
71290
71291				var meta = chart.getDatasetMeta(datasetIndex);
71292				if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
71293					meta.stack !== undefined) {
71294					hasStacks = true;
71295				}
71296			});
71297		}
71298
71299		if (opts.stacked || hasStacks) {
71300			var valuesPerStack = {};
71301
71302			helpers$1.each(datasets, function(dataset, datasetIndex) {
71303				var meta = chart.getDatasetMeta(datasetIndex);
71304				var key = [
71305					meta.type,
71306					// we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
71307					((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''),
71308					meta.stack
71309				].join('.');
71310
71311				if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
71312					if (valuesPerStack[key] === undefined) {
71313						valuesPerStack[key] = [];
71314					}
71315
71316					helpers$1.each(dataset.data, function(rawValue, index) {
71317						var values = valuesPerStack[key];
71318						var value = +me.getRightValue(rawValue);
71319						// invalid, hidden and negative values are ignored
71320						if (isNaN(value) || meta.data[index].hidden || value < 0) {
71321							return;
71322						}
71323						values[index] = values[index] || 0;
71324						values[index] += value;
71325					});
71326				}
71327			});
71328
71329			helpers$1.each(valuesPerStack, function(valuesForType) {
71330				if (valuesForType.length > 0) {
71331					var minVal = helpers$1.min(valuesForType);
71332					var maxVal = helpers$1.max(valuesForType);
71333					me.min = me.min === null ? minVal : Math.min(me.min, minVal);
71334					me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
71335				}
71336			});
71337
71338		} else {
71339			helpers$1.each(datasets, function(dataset, datasetIndex) {
71340				var meta = chart.getDatasetMeta(datasetIndex);
71341				if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
71342					helpers$1.each(dataset.data, function(rawValue, index) {
71343						var value = +me.getRightValue(rawValue);
71344						// invalid, hidden and negative values are ignored
71345						if (isNaN(value) || meta.data[index].hidden || value < 0) {
71346							return;
71347						}
71348
71349						if (me.min === null) {
71350							me.min = value;
71351						} else if (value < me.min) {
71352							me.min = value;
71353						}
71354
71355						if (me.max === null) {
71356							me.max = value;
71357						} else if (value > me.max) {
71358							me.max = value;
71359						}
71360
71361						if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) {
71362							me.minNotZero = value;
71363						}
71364					});
71365				}
71366			});
71367		}
71368
71369		// Common base implementation to handle ticks.min, ticks.max
71370		this.handleTickRangeOptions();
71371	},
71372
71373	handleTickRangeOptions: function() {
71374		var me = this;
71375		var tickOpts = me.options.ticks;
71376		var DEFAULT_MIN = 1;
71377		var DEFAULT_MAX = 10;
71378
71379		me.min = nonNegativeOrDefault(tickOpts.min, me.min);
71380		me.max = nonNegativeOrDefault(tickOpts.max, me.max);
71381
71382		if (me.min === me.max) {
71383			if (me.min !== 0 && me.min !== null) {
71384				me.min = Math.pow(10, Math.floor(helpers$1.log10(me.min)) - 1);
71385				me.max = Math.pow(10, Math.floor(helpers$1.log10(me.max)) + 1);
71386			} else {
71387				me.min = DEFAULT_MIN;
71388				me.max = DEFAULT_MAX;
71389			}
71390		}
71391		if (me.min === null) {
71392			me.min = Math.pow(10, Math.floor(helpers$1.log10(me.max)) - 1);
71393		}
71394		if (me.max === null) {
71395			me.max = me.min !== 0
71396				? Math.pow(10, Math.floor(helpers$1.log10(me.min)) + 1)
71397				: DEFAULT_MAX;
71398		}
71399		if (me.minNotZero === null) {
71400			if (me.min > 0) {
71401				me.minNotZero = me.min;
71402			} else if (me.max < 1) {
71403				me.minNotZero = Math.pow(10, Math.floor(helpers$1.log10(me.max)));
71404			} else {
71405				me.minNotZero = DEFAULT_MIN;
71406			}
71407		}
71408	},
71409
71410	buildTicks: function() {
71411		var me = this;
71412		var tickOpts = me.options.ticks;
71413		var reverse = !me.isHorizontal();
71414
71415		var generationOptions = {
71416			min: nonNegativeOrDefault(tickOpts.min),
71417			max: nonNegativeOrDefault(tickOpts.max)
71418		};
71419		var ticks = me.ticks = generateTicks$1(generationOptions, me);
71420
71421		// At this point, we need to update our max and min given the tick values since we have expanded the
71422		// range of the scale
71423		me.max = helpers$1.max(ticks);
71424		me.min = helpers$1.min(ticks);
71425
71426		if (tickOpts.reverse) {
71427			reverse = !reverse;
71428			me.start = me.max;
71429			me.end = me.min;
71430		} else {
71431			me.start = me.min;
71432			me.end = me.max;
71433		}
71434		if (reverse) {
71435			ticks.reverse();
71436		}
71437	},
71438
71439	convertTicksToLabels: function() {
71440		this.tickValues = this.ticks.slice();
71441
71442		core_scale.prototype.convertTicksToLabels.call(this);
71443	},
71444
71445	// Get the correct tooltip label
71446	getLabelForIndex: function(index, datasetIndex) {
71447		return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
71448	},
71449
71450	getPixelForTick: function(index) {
71451		return this.getPixelForValue(this.tickValues[index]);
71452	},
71453
71454	/**
71455	 * Returns the value of the first tick.
71456	 * @param {number} value - The minimum not zero value.
71457	 * @return {number} The first tick value.
71458	 * @private
71459	 */
71460	_getFirstTickValue: function(value) {
71461		var exp = Math.floor(helpers$1.log10(value));
71462		var significand = Math.floor(value / Math.pow(10, exp));
71463
71464		return significand * Math.pow(10, exp);
71465	},
71466
71467	getPixelForValue: function(value) {
71468		var me = this;
71469		var tickOpts = me.options.ticks;
71470		var reverse = tickOpts.reverse;
71471		var log10 = helpers$1.log10;
71472		var firstTickValue = me._getFirstTickValue(me.minNotZero);
71473		var offset = 0;
71474		var innerDimension, pixel, start, end, sign;
71475
71476		value = +me.getRightValue(value);
71477		if (reverse) {
71478			start = me.end;
71479			end = me.start;
71480			sign = -1;
71481		} else {
71482			start = me.start;
71483			end = me.end;
71484			sign = 1;
71485		}
71486		if (me.isHorizontal()) {
71487			innerDimension = me.width;
71488			pixel = reverse ? me.right : me.left;
71489		} else {
71490			innerDimension = me.height;
71491			sign *= -1; // invert, since the upper-left corner of the canvas is at pixel (0, 0)
71492			pixel = reverse ? me.top : me.bottom;
71493		}
71494		if (value !== start) {
71495			if (start === 0) { // include zero tick
71496				offset = valueOrDefault$a(tickOpts.fontSize, core_defaults.global.defaultFontSize);
71497				innerDimension -= offset;
71498				start = firstTickValue;
71499			}
71500			if (value !== 0) {
71501				offset += innerDimension / (log10(end) - log10(start)) * (log10(value) - log10(start));
71502			}
71503			pixel += sign * offset;
71504		}
71505		return pixel;
71506	},
71507
71508	getValueForPixel: function(pixel) {
71509		var me = this;
71510		var tickOpts = me.options.ticks;
71511		var reverse = tickOpts.reverse;
71512		var log10 = helpers$1.log10;
71513		var firstTickValue = me._getFirstTickValue(me.minNotZero);
71514		var innerDimension, start, end, value;
71515
71516		if (reverse) {
71517			start = me.end;
71518			end = me.start;
71519		} else {
71520			start = me.start;
71521			end = me.end;
71522		}
71523		if (me.isHorizontal()) {
71524			innerDimension = me.width;
71525			value = reverse ? me.right - pixel : pixel - me.left;
71526		} else {
71527			innerDimension = me.height;
71528			value = reverse ? pixel - me.top : me.bottom - pixel;
71529		}
71530		if (value !== start) {
71531			if (start === 0) { // include zero tick
71532				var offset = valueOrDefault$a(tickOpts.fontSize, core_defaults.global.defaultFontSize);
71533				value -= offset;
71534				innerDimension -= offset;
71535				start = firstTickValue;
71536			}
71537			value *= log10(end) - log10(start);
71538			value /= innerDimension;
71539			value = Math.pow(10, log10(start) + value);
71540		}
71541		return value;
71542	}
71543});
71544
71545// INTERNAL: static default options, registered in src/index.js
71546var _defaults$2 = defaultConfig$2;
71547scale_logarithmic._defaults = _defaults$2;
71548
71549var valueOrDefault$b = helpers$1.valueOrDefault;
71550var valueAtIndexOrDefault$1 = helpers$1.valueAtIndexOrDefault;
71551var resolve$7 = helpers$1.options.resolve;
71552
71553var defaultConfig$3 = {
vendor: 11,713 bytes, lines 71554-71950
71554	display: true,
71555
71556	// Boolean - Whether to animate scaling the chart from the centre
71557	animate: true,
71558	position: 'chartArea',
71559
71560	angleLines: {
71561		display: true,
71562		color: 'rgba(0, 0, 0, 0.1)',
71563		lineWidth: 1,
71564		borderDash: [],
71565		borderDashOffset: 0.0
71566	},
71567
71568	gridLines: {
71569		circular: false
71570	},
71571
71572	// label settings
71573	ticks: {
71574		// Boolean - Show a backdrop to the scale label
71575		showLabelBackdrop: true,
71576
71577		// String - The colour of the label backdrop
71578		backdropColor: 'rgba(255,255,255,0.75)',
71579
71580		// Number - The backdrop padding above & below the label in pixels
71581		backdropPaddingY: 2,
71582
71583		// Number - The backdrop padding to the side of the label in pixels
71584		backdropPaddingX: 2,
71585
71586		callback: core_ticks.formatters.linear
71587	},
71588
71589	pointLabels: {
71590		// Boolean - if true, show point labels
71591		display: true,
71592
71593		// Number - Point label font size in pixels
71594		fontSize: 10,
71595
71596		// Function - Used to convert point labels
71597		callback: function(label) {
71598			return label;
71599		}
71600	}
71601};
71602
71603function getValueCount(scale) {
71604	var opts = scale.options;
71605	return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0;
71606}
71607
71608function getTickBackdropHeight(opts) {
71609	var tickOpts = opts.ticks;
71610
71611	if (tickOpts.display && opts.display) {
71612		return valueOrDefault$b(tickOpts.fontSize, core_defaults.global.defaultFontSize) + tickOpts.backdropPaddingY * 2;
71613	}
71614	return 0;
71615}
71616
71617function measureLabelSize(ctx, lineHeight, label) {
71618	if (helpers$1.isArray(label)) {
71619		return {
71620			w: helpers$1.longestText(ctx, ctx.font, label),
71621			h: label.length * lineHeight
71622		};
71623	}
71624
71625	return {
71626		w: ctx.measureText(label).width,
71627		h: lineHeight
71628	};
71629}
71630
71631function determineLimits(angle, pos, size, min, max) {
71632	if (angle === min || angle === max) {
71633		return {
71634			start: pos - (size / 2),
71635			end: pos + (size / 2)
71636		};
71637	} else if (angle < min || angle > max) {
71638		return {
71639			start: pos - size,
71640			end: pos
71641		};
71642	}
71643
71644	return {
71645		start: pos,
71646		end: pos + size
71647	};
71648}
71649
71650/**
71651 * Helper function to fit a radial linear scale with point labels
71652 */
71653function fitWithPointLabels(scale) {
71654
71655	// Right, this is really confusing and there is a lot of maths going on here
71656	// The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
71657	//
71658	// Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
71659	//
71660	// Solution:
71661	//
71662	// We assume the radius of the polygon is half the size of the canvas at first
71663	// at each index we check if the text overlaps.
71664	//
71665	// Where it does, we store that angle and that index.
71666	//
71667	// After finding the largest index and angle we calculate how much we need to remove
71668	// from the shape radius to move the point inwards by that x.
71669	//
71670	// We average the left and right distances to get the maximum shape radius that can fit in the box
71671	// along with labels.
71672	//
71673	// Once we have that, we can find the centre point for the chart, by taking the x text protrusion
71674	// on each side, removing that from the size, halving it and adding the left x protrusion width.
71675	//
71676	// This will mean we have a shape fitted to the canvas, as large as it can be with the labels
71677	// and position it in the most space efficient manner
71678	//
71679	// https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
71680
71681	var plFont = helpers$1.options._parseFont(scale.options.pointLabels);
71682
71683	// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
71684	// Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
71685	var furthestLimits = {
71686		l: 0,
71687		r: scale.width,
71688		t: 0,
71689		b: scale.height - scale.paddingTop
71690	};
71691	var furthestAngles = {};
71692	var i, textSize, pointPosition;
71693
71694	scale.ctx.font = plFont.string;
71695	scale._pointLabelSizes = [];
71696
71697	var valueCount = getValueCount(scale);
71698	for (i = 0; i < valueCount; i++) {
71699		pointPosition = scale.getPointPosition(i, scale.drawingArea + 5);
71700		textSize = measureLabelSize(scale.ctx, plFont.lineHeight, scale.pointLabels[i] || '');
71701		scale._pointLabelSizes[i] = textSize;
71702
71703		// Add quarter circle to make degree 0 mean top of circle
71704		var angleRadians = scale.getIndexAngle(i);
71705		var angle = helpers$1.toDegrees(angleRadians) % 360;
71706		var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
71707		var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
71708
71709		if (hLimits.start < furthestLimits.l) {
71710			furthestLimits.l = hLimits.start;
71711			furthestAngles.l = angleRadians;
71712		}
71713
71714		if (hLimits.end > furthestLimits.r) {
71715			furthestLimits.r = hLimits.end;
71716			furthestAngles.r = angleRadians;
71717		}
71718
71719		if (vLimits.start < furthestLimits.t) {
71720			furthestLimits.t = vLimits.start;
71721			furthestAngles.t = angleRadians;
71722		}
71723
71724		if (vLimits.end > furthestLimits.b) {
71725			furthestLimits.b = vLimits.end;
71726			furthestAngles.b = angleRadians;
71727		}
71728	}
71729
71730	scale.setReductions(scale.drawingArea, furthestLimits, furthestAngles);
71731}
71732
71733function getTextAlignForAngle(angle) {
71734	if (angle === 0 || angle === 180) {
71735		return 'center';
71736	} else if (angle < 180) {
71737		return 'left';
71738	}
71739
71740	return 'right';
71741}
71742
71743function fillText(ctx, text, position, lineHeight) {
71744	var y = position.y + lineHeight / 2;
71745	var i, ilen;
71746
71747	if (helpers$1.isArray(text)) {
71748		for (i = 0, ilen = text.length; i < ilen; ++i) {
71749			ctx.fillText(text[i], position.x, y);
71750			y += lineHeight;
71751		}
71752	} else {
71753		ctx.fillText(text, position.x, y);
71754	}
71755}
71756
71757function adjustPointPositionForLabelHeight(angle, textSize, position) {
71758	if (angle === 90 || angle === 270) {
71759		position.y -= (textSize.h / 2);
71760	} else if (angle > 270 || angle < 90) {
71761		position.y -= textSize.h;
71762	}
71763}
71764
71765function drawPointLabels(scale) {
71766	var ctx = scale.ctx;
71767	var opts = scale.options;
71768	var angleLineOpts = opts.angleLines;
71769	var gridLineOpts = opts.gridLines;
71770	var pointLabelOpts = opts.pointLabels;
71771	var lineWidth = valueOrDefault$b(angleLineOpts.lineWidth, gridLineOpts.lineWidth);
71772	var lineColor = valueOrDefault$b(angleLineOpts.color, gridLineOpts.color);
71773	var tickBackdropHeight = getTickBackdropHeight(opts);
71774
71775	ctx.save();
71776	ctx.lineWidth = lineWidth;
71777	ctx.strokeStyle = lineColor;
71778	if (ctx.setLineDash) {
71779		ctx.setLineDash(resolve$7([angleLineOpts.borderDash, gridLineOpts.borderDash, []]));
71780		ctx.lineDashOffset = resolve$7([angleLineOpts.borderDashOffset, gridLineOpts.borderDashOffset, 0.0]);
71781	}
71782
71783	var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
71784
71785	// Point Label Font
71786	var plFont = helpers$1.options._parseFont(pointLabelOpts);
71787
71788	ctx.font = plFont.string;
71789	ctx.textBaseline = 'middle';
71790
71791	for (var i = getValueCount(scale) - 1; i >= 0; i--) {
71792		if (angleLineOpts.display && lineWidth && lineColor) {
71793			var outerPosition = scale.getPointPosition(i, outerDistance);
71794			ctx.beginPath();
71795			ctx.moveTo(scale.xCenter, scale.yCenter);
71796			ctx.lineTo(outerPosition.x, outerPosition.y);
71797			ctx.stroke();
71798		}
71799
71800		if (pointLabelOpts.display) {
71801			// Extra pixels out for some label spacing
71802			var extra = (i === 0 ? tickBackdropHeight / 2 : 0);
71803			var pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5);
71804
71805			// Keep this in loop since we may support array properties here
71806			var pointLabelFontColor = valueAtIndexOrDefault$1(pointLabelOpts.fontColor, i, core_defaults.global.defaultFontColor);
71807			ctx.fillStyle = pointLabelFontColor;
71808
71809			var angleRadians = scale.getIndexAngle(i);
71810			var angle = helpers$1.toDegrees(angleRadians);
71811			ctx.textAlign = getTextAlignForAngle(angle);
71812			adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition);
71813			fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.lineHeight);
71814		}
71815	}
71816	ctx.restore();
71817}
71818
71819function drawRadiusLine(scale, gridLineOpts, radius, index) {
71820	var ctx = scale.ctx;
71821	var circular = gridLineOpts.circular;
71822	var valueCount = getValueCount(scale);
71823	var lineColor = valueAtIndexOrDefault$1(gridLineOpts.color, index - 1);
71824	var lineWidth = valueAtIndexOrDefault$1(gridLineOpts.lineWidth, index - 1);
71825	var pointPosition;
71826
71827	if ((!circular && !valueCount) || !lineColor || !lineWidth) {
71828		return;
71829	}
71830
71831	ctx.save();
71832	ctx.strokeStyle = lineColor;
71833	ctx.lineWidth = lineWidth;
71834	if (ctx.setLineDash) {
71835		ctx.setLineDash(gridLineOpts.borderDash || []);
71836		ctx.lineDashOffset = gridLineOpts.borderDashOffset || 0.0;
71837	}
71838
71839	ctx.beginPath();
71840	if (circular) {
71841		// Draw circular arcs between the points
71842		ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2);
71843	} else {
71844		// Draw straight lines connecting each index
71845		pointPosition = scale.getPointPosition(0, radius);
71846		ctx.moveTo(pointPosition.x, pointPosition.y);
71847
71848		for (var i = 1; i < valueCount; i++) {
71849			pointPosition = scale.getPointPosition(i, radius);
71850			ctx.lineTo(pointPosition.x, pointPosition.y);
71851		}
71852	}
71853	ctx.closePath();
71854	ctx.stroke();
71855	ctx.restore();
71856}
71857
71858function numberOrZero(param) {
71859	return helpers$1.isNumber(param) ? param : 0;
71860}
71861
71862var scale_radialLinear = scale_linearbase.extend({
71863	setDimensions: function() {
71864		var me = this;
71865
71866		// Set the unconstrained dimension before label rotation
71867		me.width = me.maxWidth;
71868		me.height = me.maxHeight;
71869		me.paddingTop = getTickBackdropHeight(me.options) / 2;
71870		me.xCenter = Math.floor(me.width / 2);
71871		me.yCenter = Math.floor((me.height - me.paddingTop) / 2);
71872		me.drawingArea = Math.min(me.height - me.paddingTop, me.width) / 2;
71873	},
71874
71875	determineDataLimits: function() {
71876		var me = this;
71877		var chart = me.chart;
71878		var min = Number.POSITIVE_INFINITY;
71879		var max = Number.NEGATIVE_INFINITY;
71880
71881		helpers$1.each(chart.data.datasets, function(dataset, datasetIndex) {
71882			if (chart.isDatasetVisible(datasetIndex)) {
71883				var meta = chart.getDatasetMeta(datasetIndex);
71884
71885				helpers$1.each(dataset.data, function(rawValue, index) {
71886					var value = +me.getRightValue(rawValue);
71887					if (isNaN(value) || meta.data[index].hidden) {
71888						return;
71889					}
71890
71891					min = Math.min(value, min);
71892					max = Math.max(value, max);
71893				});
71894			}
71895		});
71896
71897		me.min = (min === Number.POSITIVE_INFINITY ? 0 : min);
71898		me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max);
71899
71900		// Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
71901		me.handleTickRangeOptions();
71902	},
71903
71904	// Returns the maximum number of ticks based on the scale dimension
71905	_computeTickLimit: function() {
71906		return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));
71907	},
71908
71909	convertTicksToLabels: function() {
71910		var me = this;
71911
71912		scale_linearbase.prototype.convertTicksToLabels.call(me);
71913
71914		// Point labels
71915		me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me);
71916	},
71917
71918	getLabelForIndex: function(index, datasetIndex) {
71919		return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
71920	},
71921
71922	fit: function() {
71923		var me = this;
71924		var opts = me.options;
71925
71926		if (opts.display && opts.pointLabels.display) {
71927			fitWithPointLabels(me);
71928		} else {
71929			me.setCenterPoint(0, 0, 0, 0);
71930		}
71931	},
71932
71933	/**
71934	 * Set radius reductions and determine new radius and center point
71935	 * @private
71936	 */
71937	setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) {
71938		var me = this;
71939		var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l);
71940		var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r);
71941		var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t);
71942		var radiusReductionBottom = -Math.max(furthestLimits.b - (me.height - me.paddingTop), 0) / Math.cos(furthestAngles.b);
71943
71944		radiusReductionLeft = numberOrZero(radiusReductionLeft);
71945		radiusReductionRight = numberOrZero(radiusReductionRight);
71946		radiusReductionTop = numberOrZero(radiusReductionTop);
71947		radiusReductionBottom = numberOrZero(radiusReductionBottom);
71948
71949		me.drawingArea = Math.min(
71950			Math.floor(largestPossibleRadius - (radiusReductionLeft + radiu
71950sReductionRight) / 2),
71951			Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2));
71952		me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom);
71953	},
71954
71955	setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) {
71956		var me = this;
71957		var maxRight = me.width - rightMovement - me.drawingArea;
71958		var maxLeft = leftMovement + me.drawingArea;
71959		var maxTop = topMovement + me.drawingArea;
71960		var maxBottom = (me.height - me.paddingTop) - bottomMovement - me.drawingArea;
71961
71962		me.xCenter = Math.floor(((maxLeft + maxRight) / 2) + me.left);
71963		me.yCenter = Math.floor(((maxTop + maxBottom) / 2) + me.top + me.paddingTop);
71964	},
71965
71966	getIndexAngle: function(index) {
71967		var angleMultiplier = (Math.PI * 2) / getValueCount(this);
71968		var startAngle = this.chart.options && this.chart.options.startAngle ?
71969			this.chart.options.startAngle :
71970			0;
71971
71972		var startAngleRadians = startAngle * Math.PI * 2 / 360;
71973
71974		// Start from the top instead of right, so remove a quarter of the circle
71975		return index * angleMultiplier + startAngleRadians;
71976	},
71977
71978	getDistanceFromCenterForValue: function(value) {
71979		var me = this;
71980
71981		if (value === null) {
71982			return 0; // null always in center
71983		}
71984
71985		// Take into account half font size + the yPadding of the top value
71986		var scalingFactor = me.drawingArea / (me.max - me.min);
71987		if (me.options.ticks.reverse) {
71988			return (me.max - value) * scalingFactor;
71989		}
71990		return (value - me.min) * scalingFactor;
71991	},
71992
71993	getPointPosition: function(index, distanceFromCenter) {
71994		var me = this;
71995		var thisAngle = me.getIndexAngle(index) - (Math.PI / 2);
71996		return {
71997			x: Math.cos(thisAngle) * distanceFromCenter + me.xCenter,
71998			y: Math.sin(thisAngle) * distanceFromCenter + me.yCenter
71999		};
72000	},
72001
72002	getPointPositionForValue: function(index, value) {
72003		return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
72004	},
72005
72006	getBasePosition: function() {
72007		var me = this;
72008		var min = me.min;
72009		var max = me.max;
72010
72011		return me.getPointPositionForValue(0,
72012			me.beginAtZero ? 0 :
72013			min < 0 && max < 0 ? max :
72014			min > 0 && max > 0 ? min :
72015			0);
72016	},
72017
72018	draw: function() {
72019		var me = this;
72020		var opts = me.options;
72021		var gridLineOpts = opts.gridLines;
72022		var tickOpts = opts.ticks;
72023
72024		if (opts.display) {
72025			var ctx = me.ctx;
72026			var startAngle = this.getIndexAngle(0);
72027			var tickFont = helpers$1.options._parseFont(tickOpts);
72028
72029			if (opts.angleLines.display || opts.pointLabels.display) {
72030				drawPointLabels(me);
72031			}
72032
72033			helpers$1.each(me.ticks, function(label, index) {
72034				// Don't draw a centre value (if it is minimum)
72035				if (index > 0 || tickOpts.reverse) {
72036					var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]);
72037
72038					// Draw circular lines around the scale
72039					if (gridLineOpts.display && index !== 0) {
72040						drawRadiusLine(me, gridLineOpts, yCenterOffset, index);
72041					}
72042
72043					if (tickOpts.display) {
72044						var tickFontColor = valueOrDefault$b(tickOpts.fontColor, core_defaults.global.defaultFontColor);
72045						ctx.font = tickFont.string;
72046
72047						ctx.save();
72048						ctx.translate(me.xCenter, me.yCenter);
72049						ctx.rotate(startAngle);
72050
72051						if (tickOpts.showLabelBackdrop) {
72052							var labelWidth = ctx.measureText(label).width;
72053							ctx.fillStyle = tickOpts.backdropColor;
72054							ctx.fillRect(
72055								-labelWidth / 2 - tickOpts.backdropPaddingX,
72056								-yCenterOffset - tickFont.size / 2 - tickOpts.backdropPaddingY,
72057								labelWidth + tickOpts.backdropPaddingX * 2,
72058								tickFont.size + tickOpts.backdropPaddingY * 2
72059							);
72060						}
72061
72062						ctx.textAlign = 'center';
72063						ctx.textBaseline = 'middle';
72064						ctx.fillStyle = tickFontColor;
72065						ctx.fillText(label, 0, -yCenterOffset);
72066						ctx.restore();
72067					}
72068				}
72069			});
72070		}
72071	}
72072});
72073
72074// INTERNAL: static default options, registered in src/index.js
72075var _defaults$3 = defaultConfig$3;
72076scale_radialLinear._defaults = _defaults$3;
72077
72078var valueOrDefault$c = helpers$1.valueOrDefault;
72079
72080// Integer constants are from the ES6 spec.
72081var MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991;
72082var MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
72083
72084var INTERVALS = {
72085	millisecond: {
72086		common: true,
72087		size: 1,
72088		steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]
72089	},
vendor: 7,892 bytes, lines 72090-72386
72090	second: {
72091		common: true,
72092		size: 1000,
72093		steps: [1, 2, 5, 10, 15, 30]
72094	},
72095	minute: {
72096		common: true,
72097		size: 60000,
72098		steps: [1, 2, 5, 10, 15, 30]
72099	},
72100	hour: {
72101		common: true,
72102		size: 3600000,
72103		steps: [1, 2, 3, 6, 12]
72104	},
72105	day: {
72106		common: true,
72107		size: 86400000,
72108		steps: [1, 2, 5]
72109	},
72110	week: {
72111		common: false,
72112		size: 604800000,
72113		steps: [1, 2, 3, 4]
72114	},
72115	month: {
72116		common: true,
72117		size: 2.628e9,
72118		steps: [1, 2, 3]
72119	},
72120	quarter: {
72121		common: false,
72122		size: 7.884e9,
72123		steps: [1, 2, 3, 4]
72124	},
72125	year: {
72126		common: true,
72127		size: 3.154e10
72128	}
72129};
72130
72131var UNITS = Object.keys(INTERVALS);
72132
72133function sorter(a, b) {
72134	return a - b;
72135}
72136
72137function arrayUnique(items) {
72138	var hash = {};
72139	var out = [];
72140	var i, ilen, item;
72141
72142	for (i = 0, ilen = items.length; i < ilen; ++i) {
72143		item = items[i];
72144		if (!hash[item]) {
72145			hash[item] = true;
72146			out.push(item);
72147		}
72148	}
72149
72150	return out;
72151}
72152
72153/**
72154 * Returns an array of {time, pos} objects used to interpolate a specific `time` or position
72155 * (`pos`) on the scale, by searching entries before and after the requested value. `pos` is
72156 * a decimal between 0 and 1: 0 being the start of the scale (left or top) and 1 the other
72157 * extremity (left + width or top + height). Note that it would be more optimized to directly
72158 * store pre-computed pixels, but the scale dimensions are not guaranteed at the time we need
72159 * to create the lookup table. The table ALWAYS contains at least two items: min and max.
72160 *
72161 * @param {number[]} timestamps - timestamps sorted from lowest to highest.
72162 * @param {string} distribution - If 'linear', timestamps will be spread linearly along the min
72163 * and max range, so basically, the table will contains only two items: {min, 0} and {max, 1}.
72164 * If 'series', timestamps will be positioned at the same distance from each other. In this
72165 * case, only timestamps that break the time linearity are registered, meaning that in the
72166 * best case, all timestamps are linear, the table contains only min and max.
72167 */
72168function buildLookupTable(timestamps, min, max, distribution) {
72169	if (distribution === 'linear' || !timestamps.length) {
72170		return [
72171			{time: min, pos: 0},
72172			{time: max, pos: 1}
72173		];
72174	}
72175
72176	var table = [];
72177	var items = [min];
72178	var i, ilen, prev, curr, next;
72179
72180	for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
72181		curr = timestamps[i];
72182		if (curr > min && curr < max) {
72183			items.push(curr);
72184		}
72185	}
72186
72187	items.push(max);
72188
72189	for (i = 0, ilen = items.length; i < ilen; ++i) {
72190		next = items[i + 1];
72191		prev = items[i - 1];
72192		curr = items[i];
72193
72194		// only add points that breaks the scale linearity
72195		if (prev === undefined || next === undefined || Math.round((next + prev) / 2) !== curr) {
72196			table.push({time: curr, pos: i / (ilen - 1)});
72197		}
72198	}
72199
72200	return table;
72201}
72202
72203// @see adapted from https://www.anujgakhar.com/2014/03/01/binary-search-in-javascript/
72204function lookup(table, key, value) {
72205	var lo = 0;
72206	var hi = table.length - 1;
72207	var mid, i0, i1;
72208
72209	while (lo >= 0 && lo <= hi) {
72210		mid = (lo + hi) >> 1;
72211		i0 = table[mid - 1] || null;
72212		i1 = table[mid];
72213
72214		if (!i0) {
72215			// given value is outside table (before first item)
72216			return {lo: null, hi: i1};
72217		} else if (i1[key] < value) {
72218			lo = mid + 1;
72219		} else if (i0[key] > value) {
72220			hi = mid - 1;
72221		} else {
72222			return {lo: i0, hi: i1};
72223		}
72224	}
72225
72226	// given value is outside table (after last item)
72227	return {lo: i1, hi: null};
72228}
72229
72230/**
72231 * Linearly interpolates the given source `value` using the table items `skey` values and
72232 * returns the associated `tkey` value. For example, interpolate(table, 'time', 42, 'pos')
72233 * returns the position for a timestamp equal to 42. If value is out of bounds, values at
72234 * index [0, 1] or [n - 1, n] are used for the interpolation.
72235 */
72236function interpolate$1(table, skey, sval, tkey) {
72237	var range = lookup(table, skey, sval);
72238
72239	// Note: the lookup table ALWAYS contains at least 2 items (min and max)
72240	var prev = !range.lo ? table[0] : !range.hi ? table[table.length - 2] : range.lo;
72241	var next = !range.lo ? table[1] : !range.hi ? table[table.length - 1] : range.hi;
72242
72243	var span = next[skey] - prev[skey];
72244	var ratio = span ? (sval - prev[skey]) / span : 0;
72245	var offset = (next[tkey] - prev[tkey]) * ratio;
72246
72247	return prev[tkey] + offset;
72248}
72249
72250function toTimestamp(scale, input) {
72251	var adapter = scale._adapter;
72252	var options = scale.options.time;
72253	var parser = options.parser;
72254	var format = parser || options.format;
72255	var value = input;
72256
72257	if (typeof parser === 'function') {
72258		value = parser(value);
72259	}
72260
72261	// Only parse if its not a timestamp already
72262	if (!helpers$1.isFinite(value)) {
72263		value = typeof format === 'string'
72264			? adapter.parse(value, format)
72265			: adapter.parse(value);
72266	}
72267
72268	if (value !== null) {
72269		return +value;
72270	}
72271
72272	// Labels are in an incompatible format and no `parser` has been provided.
72273	// The user might still use the deprecated `format` option for parsing.
72274	if (!parser && typeof format === 'function') {
72275		value = format(input);
72276
72277		// `format` could return something else than a timestamp, if so, parse it
72278		if (!helpers$1.isFinite(value)) {
72279			value = adapter.parse(value);
72280		}
72281	}
72282
72283	return value;
72284}
72285
72286function parse(scale, input) {
72287	if (helpers$1.isNullOrUndef(input)) {
72288		return null;
72289	}
72290
72291	var options = scale.options.time;
72292	var value = toTimestamp(scale, scale.getRightValue(input));
72293	if (value === null) {
72294		return value;
72295	}
72296
72297	if (options.round) {
72298		value = +scale._adapter.startOf(value, options.round);
72299	}
72300
72301	return value;
72302}
72303
72304/**
72305 * Returns the number of unit to skip to be able to display up to `capacity` number of ticks
72306 * in `unit` for the given `min` / `max` range and respecting the interval steps constraints.
72307 */
72308function determineStepSize(min, max, unit, capacity) {
72309	var range = max - min;
72310	var interval = INTERVALS[unit];
72311	var milliseconds = interval.size;
72312	var steps = interval.steps;
72313	var i, ilen, factor;
72314
72315	if (!steps) {
72316		return Math.ceil(range / (capacity * milliseconds));
72317	}
72318
72319	for (i = 0, ilen = steps.length; i < ilen; ++i) {
72320		factor = steps[i];
72321		if (Math.ceil(range / (milliseconds * factor)) <= capacity) {
72322			break;
72323		}
72324	}
72325
72326	return factor;
72327}
72328
72329/**
72330 * Figures out what unit results in an appropriate number of auto-generated ticks
72331 */
72332function determineUnitForAutoTicks(minUnit, min, max, capacity) {
72333	var ilen = UNITS.length;
72334	var i, interval, factor;
72335
72336	for (i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) {
72337		interval = INTERVALS[UNITS[i]];
72338		factor = interval.steps ? interval.steps[interval.steps.length - 1] : MAX_INTEGER;
72339
72340		if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {
72341			return UNITS[i];
72342		}
72343	}
72344
72345	return UNITS[ilen - 1];
72346}
72347
72348/**
72349 * Figures out what unit to format a set of ticks with
72350 */
72351function determineUnitForFormatting(scale, ticks, minUnit, min, max) {
72352	var ilen = UNITS.length;
72353	var i, unit;
72354
72355	for (i = ilen - 1; i >= UNITS.indexOf(minUnit); i--) {
72356		unit = UNITS[i];
72357		if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= ticks.length) {
72358			return unit;
72359		}
72360	}
72361
72362	return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];
72363}
72364
72365function determineMajorUnit(unit) {
72366	for (var i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) {
72367		if (INTERVALS[UNITS[i]].common) {
72368			return UNITS[i];
72369		}
72370	}
72371}
72372
72373/**
72374 * Generates a maximum of `capacity` timestamps between min and max, rounded to the
72375 * `minor` unit, aligned on the `major` unit and using the given scale time `options`.
72376 * Important: this method can return ticks outside the min and max range, it's the
72377 * responsibility of the calling code to clamp values if needed.
72378 */
72379function generate(scale, min, max, capacity) {
72380	var adapter = scale._adapter;
72381	var options = scale.options;
72382	var timeOpts = options.time;
72383	var minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, capacity);
72384	var major = determineMajorUnit(minor);
72385	var stepSize = valueOrDefault$c(timeOpts.stepSize, timeOpts.unitStepSize);
72386	var weekday = minor === 'week' ? timeOpts.isoWeekday : false;
72387	var majorTicksEnabled = options.ticks.major.enabled;
72388	var interval = INTERVALS[minor];
72389	var first = min;
72390	var last = max;
72391	var ticks = [];
72392	var time;
72393
72394	if (!stepSize) {
72395		stepSize = determineStepSize(min, max, minor, capacity);
72396	}
72397
72398	// For 'week' unit, handle the first day of week option
72399	if (weekday) {
72400		first = +adapter.startOf(first, 'isoWeek', weekday);
72401		last = +adapter.startOf(last, 'isoWeek', weekday);
72402	}
72403
72404	// Align first/last ticks on unit
72405	first = +adapter.startOf(first, weekday ? 'day' : minor);
72406	last = +adapter.startOf(last, weekday ? 'day' : minor);
72407
72408	// Make sure that the last tick include max
72409	if (last < max) {
72410		last = +adapter.add(last, 1, minor);
72411	}
72412
72413	time = first;
72414
72415	if (majorTicksEnabled && major && !weekday && !timeOpts.round) {
72416		// Align the first tick on the previous `minor` unit aligned on the `major` unit:
72417		// we first aligned time on the previous `major` unit then add the number of full
72418		// stepSize there is between first and the previous major time.
72419		time = +adapter.startOf(time, major);
72420		time = +adapter.add(time, ~~((first - time) / (interval.size * stepSize)) * stepSize, minor);
72421	}
72422
72423	for (; time < last; time = +adapter.add(time, stepSize, minor)) {
72424		ticks.push(+time);
72425	}
72426
72427	ticks.push(+time);
72428
72429	return ticks;
72430}
72431
72432/**
72433 * Returns the start and end offsets from edges in the form of {start, end}
72434 * where each value is a relative width to the scale and ranges between 0 and 1.
72435 * They add extra margins on the both sides by scaling down the original scale.
72436 * Offsets are added when the `offset` option is true.
72437 */
72438function computeOffsets(table, ticks, min, max, options) {
72439	var start = 0;
72440	var end = 0;
72441	var first, last;
72442
72443	if (options.offset && ticks.length) {
72444		if (!options.time.min) {
72445			first = interpolate$1(table, 'time', ticks[0], 'pos');
72446			if (ticks.length === 1) {
72447				start = 1 - first;
72448			} else {
72449				start = (interpolate$1(table, 'time', ticks[1], 'pos') - first) / 2;
72450			}
72451		}
72452		if (!options.time.max) {
72453			last = interpolate$1(table, 'time', ticks[ticks.length - 1], 'pos');
72454			if (ticks.length === 1) {
72455				end = last;
72456			} else {
72457				end = (last - interpolate$1(table, 'time', ticks[ticks.length - 2], 'pos')) / 2;
72458			}
72459		}
72460	}
72461
72462	return {start: start, end: end};
72463}
72464
72465function ticksFromTimestamps(scale, values, majorUnit) {
72466	var ticks = [];
72467	var i, ilen, value, major;
72468
72469	for (i = 0, ilen = values.length; i < ilen; ++i) {
72470		value = values[i];
72471		major = majorUnit ? value === +scale._adapter.startOf(value, majorUnit) : false;
72472
72473		ticks.push({
72474			value: value,
72475			major: major
72476		});
72477	}
72478
72479	return ticks;
72480}
72481
72482var defaultConfig$4 = {
72483	position: 'bottom',
72484
72485	/**
72486	 * Data distribution along the scale:
72487	 * - 'linear': data are spread according to their time (distances can vary),
72488	 * - 'series': data are spread at the same distance from each other.
72489	 * @see https://github.com/chartjs/Chart.js/pull/4507
72490	 * @since 2.7.0
72491	 */
72492	distribution: 'linear',
72493
72494	/**
72495	 * Scale boundary strategy (bypassed by min/max time options)
72496	 * - `data`: make sure data are fully visible, ticks outside are removed
72497	 * - `ticks`: make sure ticks are fully visible, data outside are truncated
72498	 * @see https://github.com/chartjs/Chart.js/pull/4556
72499	 * @since 2.7.0
72500	 */
72501	bounds: 'data',
72502
72503	adapters: {},
72504	time: {
72505		parser: false, // false == a pattern string from https://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
72506		format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from https://momentjs.com/docs/#/parsing/string-format/
72507		unit: false, // false == automatic or override with week, month, year, etc.
72508		round: false, // none, or override with week, month, year, etc.
72509		displayFormat: false, // DEPRECATED
72510		isoWeekday: false, // override week start day - see https://momentjs.com/docs/#/get-set/iso-weekday/
72511		minUnit: 'millisecond',
72512		displayFormats: {}
72513	},
72514	ticks: {
72515		autoSkip: false,
72516
72517		/**
72518		 * Ticks generation input values:
72519		 * - 'auto': generates "optimal" ticks based on scale size and time options.
72520		 * - 'data': generates ticks from data (including labels from data {t|x|y} objects).
72521		 * - 'labels': generates ticks from user given `data.labels` values ONLY.
72522		 * @see https://github.com/chartjs/Chart.js/pull/4507
72523		 * @since 2.7.0
72524		 */
72525		source: 'auto',
72526
72527		major: {
72528			enabled: false
72529		}
72530	}
72531};
72532
72533var scale_time = core_scale.extend({
72534	initialize: function() {
72535		this.mergeTicksOptions();
72536		core_scale.prototype.initialize.call(this);
72537	},
72538
72539	update: function() {
72540		var me = this;
72541		var options = me.options;
72542		var time = options.time || (options.time = {});
72543		var adapter = me._adapter = new core_adapters._date(options.adapters.date);
72544
72545		// DEPRECATIONS: output a message only one time per update
72546		if (time.format) {
72547			console.warn('options.time.format is deprecated and replaced by options.time.parser.');
72548		}
72549
72550		// Backward compatibility: before introducing adapter, `displayFormats` was
72551		// supposed to contain *all* unit/string pairs but this can't be resolved
vendor: 7,553 bytes, lines 72552-72814
72552		// when loading the scale (adapters are loaded afterward), so let's populate
72553		// missing formats on update
72554		helpers$1.mergeIf(time.displayFormats, adapter.formats());
72555
72556		return core_scale.prototype.update.apply(me, arguments);
72557	},
72558
72559	/**
72560	 * Allows data to be referenced via 't' attribute
72561	 */
72562	getRightValue: function(rawValue) {
72563		if (rawValue && rawValue.t !== undefined) {
72564			rawValue = rawValue.t;
72565		}
72566		return core_scale.prototype.getRightValue.call(this, rawValue);
72567	},
72568
72569	determineDataLimits: function() {
72570		var me = this;
72571		var chart = me.chart;
72572		var adapter = me._adapter;
72573		var timeOpts = me.options.time;
72574		var unit = timeOpts.unit || 'day';
72575		var min = MAX_INTEGER;
72576		var max = MIN_INTEGER;
72577		var timestamps = [];
72578		var datasets = [];
72579		var labels = [];
72580		var i, j, ilen, jlen, data, timestamp;
72581		var dataLabels = chart.data.labels || [];
72582
72583		// Convert labels to timestamps
72584		for (i = 0, ilen = dataLabels.length; i < ilen; ++i) {
72585			labels.push(parse(me, dataLabels[i]));
72586		}
72587
72588		// Convert data to timestamps
72589		for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
72590			if (chart.isDatasetVisible(i)) {
72591				data = chart.data.datasets[i].data;
72592
72593				// Let's consider that all data have the same format.
72594				if (helpers$1.isObject(data[0])) {
72595					datasets[i] = [];
72596
72597					for (j = 0, jlen = data.length; j < jlen; ++j) {
72598						timestamp = parse(me, data[j]);
72599						timestamps.push(timestamp);
72600						datasets[i][j] = timestamp;
72601					}
72602				} else {
72603					for (j = 0, jlen = labels.length; j < jlen; ++j) {
72604						timestamps.push(labels[j]);
72605					}
72606					datasets[i] = labels.slice(0);
72607				}
72608			} else {
72609				datasets[i] = [];
72610			}
72611		}
72612
72613		if (labels.length) {
72614			// Sort labels **after** data have been converted
72615			labels = arrayUnique(labels).sort(sorter);
72616			min = Math.min(min, labels[0]);
72617			max = Math.max(max, labels[labels.length - 1]);
72618		}
72619
72620		if (timestamps.length) {
72621			timestamps = arrayUnique(timestamps).sort(sorter);
72622			min = Math.min(min, timestamps[0]);
72623			max = Math.max(max, timestamps[timestamps.length - 1]);
72624		}
72625
72626		min = parse(me, timeOpts.min) || min;
72627		max = parse(me, timeOpts.max) || max;
72628
72629		// In case there is no valid min/max, set limits based on unit time option
72630		min = min === MAX_INTEGER ? +adapter.startOf(Date.now(), unit) : min;
72631		max = max === MIN_INTEGER ? +adapter.endOf(Date.now(), unit) + 1 : max;
72632
72633		// Make sure that max is strictly higher than min (required by the lookup table)
72634		me.min = Math.min(min, max);
72635		me.max = Math.max(min + 1, max);
72636
72637		// PRIVATE
72638		me._horizontal = me.isHorizontal();
72639		me._table = [];
72640		me._timestamps = {
72641			data: timestamps,
72642			datasets: datasets,
72643			labels: labels
72644		};
72645	},
72646
72647	buildTicks: function() {
72648		var me = this;
72649		var min = me.min;
72650		var max = me.max;
72651		var options = me.options;
72652		var timeOpts = options.time;
72653		var timestamps = [];
72654		var ticks = [];
72655		var i, ilen, timestamp;
72656
72657		switch (options.ticks.source) {
72658		case 'data':
72659			timestamps = me._timestamps.data;
72660			break;
72661		case 'labels':
72662			timestamps = me._timestamps.labels;
72663			break;
72664		case 'auto':
72665		default:
72666			timestamps = generate(me, min, max, me.getLabelCapacity(min), options);
72667		}
72668
72669		if (options.bounds === 'ticks' && timestamps.length) {
72670			min = timestamps[0];
72671			max = timestamps[timestamps.length - 1];
72672		}
72673
72674		// Enforce limits with user min/max options
72675		min = parse(me, timeOpts.min) || min;
72676		max = parse(me, timeOpts.max) || max;
72677
72678		// Remove ticks outside the min/max range
72679		for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
72680			timestamp = timestamps[i];
72681			if (timestamp >= min && timestamp <= max) {
72682				ticks.push(timestamp);
72683			}
72684		}
72685
72686		me.min = min;
72687		me.max = max;
72688
72689		// PRIVATE
72690		me._unit = timeOpts.unit || determineUnitForFormatting(me, ticks, timeOpts.minUnit, me.min, me.max);
72691		me._majorUnit = determineMajorUnit(me._unit);
72692		me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution);
72693		me._offsets = computeOffsets(me._table, ticks, min, max, options);
72694
72695		if (options.ticks.reverse) {
72696			ticks.reverse();
72697		}
72698
72699		return ticksFromTimestamps(me, ticks, me._majorUnit);
72700	},
72701
72702	getLabelForIndex: function(index, datasetIndex) {
72703		var me = this;
72704		var adapter = me._adapter;
72705		var data = me.chart.data;
72706		var timeOpts = me.options.time;
72707		var label = data.labels && index < data.labels.length ? data.labels[index] : '';
72708		var value = data.datasets[datasetIndex].data[index];
72709
72710		if (helpers$1.isObject(value)) {
72711			label = me.getRightValue(value);
72712		}
72713		if (timeOpts.tooltipFormat) {
72714			return adapter.format(toTimestamp(me, label), timeOpts.tooltipFormat);
72715		}
72716		if (typeof label === 'string') {
72717			return label;
72718		}
72719		return adapter.format(toTimestamp(me, label), timeOpts.displayFormats.datetime);
72720	},
72721
72722	/**
72723	 * Function to format an individual tick mark
72724	 * @private
72725	 */
72726	tickFormatFunction: function(time, index, ticks, format) {
72727		var me = this;
72728		var adapter = me._adapter;
72729		var options = me.options;
72730		var formats = options.time.displayFormats;
72731		var minorFormat = formats[me._unit];
72732		var majorUnit = me._majorUnit;
72733		var majorFormat = formats[majorUnit];
72734		var majorTime = +adapter.startOf(time, majorUnit);
72735		var majorTickOpts = options.ticks.major;
72736		var major = majorTickOpts.enabled && majorUnit && majorFormat && time === majorTime;
72737		var label = adapter.format(time, format ? format : major ? majorFormat : minorFormat);
72738		var tickOpts = major ? majorTickOpts : options.ticks.minor;
72739		var formatter = valueOrDefault$c(tickOpts.callback, tickOpts.userCallback);
72740
72741		return formatter ? formatter(label, index, ticks) : label;
72742	},
72743
72744	convertTicksToLabels: function(ticks) {
72745		var labels = [];
72746		var i, ilen;
72747
72748		for (i = 0, ilen = ticks.length; i < ilen; ++i) {
72749			labels.push(this.tickFormatFunction(ticks[i].value, i, ticks));
72750		}
72751
72752		return labels;
72753	},
72754
72755	/**
72756	 * @private
72757	 */
72758	getPixelForOffset: function(time) {
72759		var me = this;
72760		var isReverse = me.options.ticks.reverse;
72761		var size = me._horizontal ? me.width : me.height;
72762		var start = me._horizontal ? isReverse ? me.right : me.left : isReverse ? me.bottom : me.top;
72763		var pos = interpolate$1(me._table, 'time', time, 'pos');
72764		var offset = size * (me._offsets.start + pos) / (me._offsets.start + 1 + me._offsets.end);
72765
72766		return isReverse ? start - offset : start + offset;
72767	},
72768
72769	getPixelForValue: function(value, index, datasetIndex) {
72770		var me = this;
72771		var time = null;
72772
72773		if (index !== undefined && datasetIndex !== undefined) {
72774			time = me._timestamps.datasets[datasetIndex][index];
72775		}
72776
72777		if (time === null) {
72778			time = parse(me, value);
72779		}
72780
72781		if (time !== null) {
72782			return me.getPixelForOffset(time);
72783		}
72784	},
72785
72786	getPixelForTick: function(index) {
72787		var ticks = this.getTicks();
72788		return index >= 0 && index < ticks.length ?
72789			this.getPixelForOffset(ticks[index].value) :
72790			null;
72791	},
72792
72793	getValueForPixel: function(pixel) {
72794		var me = this;
72795		var size = me._horizontal ? me.width : me.height;
72796		var start = me._horizontal ? me.left : me.top;
72797		var pos = (size ? (pixel - start) / size : 0) * (me._offsets.start + 1 + me._offsets.start) - me._offsets.end;
72798		var time = interpolate$1(me._table, 'pos', pos, 'time');
72799
72800		// DEPRECATION, we should return time directly
72801		return me._adapter._create(time);
72802	},
72803
72804	/**
72805	 * Crude approximation of what the label width might be
72806	 * @private
72807	 */
72808	getLabelWidth: function(label) {
72809		var me = this;
72810		var ticksOpts = me.options.ticks;
72811		var tickLabelWidth = me.ctx.measureText(label).width;
72812		var angle = helpers$1.toRadians(ticksOpts.maxRotation);
72813		var cosRotation = Math.cos(angle);
72814		var sinRotation = Math.sin(angle);
vendor: 143,338 bytes, lines 72815-77216
72815		var tickFontSize = valueOrDefault$c(ticksOpts.fontSize, core_defaults.global.defaultFontSize);
72816
72817		return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
72818	},
72819
72820	/**
72821	 * @private
72822	 */
72823	getLabelCapacity: function(exampleTime) {
72824		var me = this;
72825
72826		// pick the longest format (milliseconds) for guestimation
72827		var format = me.options.time.displayFormats.millisecond;
72828		var exampleLabel = me.tickFormatFunction(exampleTime, 0, [], format);
72829		var tickLabelWidth = me.getLabelWidth(exampleLabel);
72830		var innerWidth = me.isHorizontal() ? me.width : me.height;
72831		var capacity = Math.floor(innerWidth / tickLabelWidth);
72832
72833		return capacity > 0 ? capacity : 1;
72834	}
72835});
72836
72837// INTERNAL: static default options, registered in src/index.js
72838var _defaults$4 = defaultConfig$4;
72839scale_time._defaults = _defaults$4;
72840
72841var scales = {
72842	category: scale_category,
72843	linear: scale_linear,
72844	logarithmic: scale_logarithmic,
72845	radialLinear: scale_radialLinear,
72846	time: scale_time
72847};
72848
72849var moment = createCommonjsModule(function (module, exports) {
72850(function (global, factory) {
72851    module.exports = factory();
72852}(commonjsGlobal, (function () {
72853    var hookCallback;
72854
72855    function hooks () {
72856        return hookCallback.apply(null, arguments);
72857    }
72858
72859    // This is done to register the method called with moment()
72860    // without creating circular dependencies.
72861    function setHookCallback (callback) {
72862        hookCallback = callback;
72863    }
72864
72865    function isArray(input) {
72866        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
72867    }
72868
72869    function isObject(input) {
72870        // IE8 will treat undefined and null as object if it wasn't for
72871        // input != null
72872        return input != null && Object.prototype.toString.call(input) === '[object Object]';
72873    }
72874
72875    function isObjectEmpty(obj) {
72876        if (Object.getOwnPropertyNames) {
72877            return (Object.getOwnPropertyNames(obj).length === 0);
72878        } else {
72879            var k;
72880            for (k in obj) {
72881                if (obj.hasOwnProperty(k)) {
72882                    return false;
72883                }
72884            }
72885            return true;
72886        }
72887    }
72888
72889    function isUndefined(input) {
72890        return input === void 0;
72891    }
72892
72893    function isNumber(input) {
72894        return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
72895    }
72896
72897    function isDate(input) {
72898        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
72899    }
72900
72901    function map(arr, fn) {
72902        var res = [], i;
72903        for (i = 0; i < arr.length; ++i) {
72904            res.push(fn(arr[i], i));
72905        }
72906        return res;
72907    }
72908
72909    function hasOwnProp(a, b) {
72910        return Object.prototype.hasOwnProperty.call(a, b);
72911    }
72912
72913    function extend(a, b) {
72914        for (var i in b) {
72915            if (hasOwnProp(b, i)) {
72916                a[i] = b[i];
72917            }
72918        }
72919
72920        if (hasOwnProp(b, 'toString')) {
72921            a.toString = b.toString;
72922        }
72923
72924        if (hasOwnProp(b, 'valueOf')) {
72925            a.valueOf = b.valueOf;
72926        }
72927
72928        return a;
72929    }
72930
72931    function createUTC (input, format, locale, strict) {
72932        return createLocalOrUTC(input, format, locale, strict, true).utc();
72933    }
72934
72935    function defaultParsingFlags() {
72936        // We need to deep clone this object.
72937        return {
72938            empty           : false,
72939            unusedTokens    : [],
72940            unusedInput     : [],
72941            overflow        : -2,
72942            charsLeftOver   : 0,
72943            nullInput       : false,
72944            invalidMonth    : null,
72945            invalidFormat   : false,
72946            userInvalidated : false,
72947            iso             : false,
72948            parsedDateParts : [],
72949            meridiem        : null,
72950            rfc2822         : false,
72951            weekdayMismatch : false
72952        };
72953    }
72954
72955    function getParsingFlags(m) {
72956        if (m._pf == null) {
72957            m._pf = defaultParsingFlags();
72958        }
72959        return m._pf;
72960    }
72961
72962    var some;
72963    if (Array.prototype.some) {
72964        some = Array.prototype.some;
72965    } else {
72966        some = function (fun) {
72967            var t = Object(this);
72968            var len = t.length >>> 0;
72969
72970            for (var i = 0; i < len; i++) {
72971                if (i in t && fun.call(this, t[i], i, t)) {
72972                    return true;
72973                }
72974            }
72975
72976            return false;
72977        };
72978    }
72979
72980    function isValid(m) {
72981        if (m._isValid == null) {
72982            var flags = getParsingFlags(m);
72983            var parsedParts = some.call(flags.parsedDateParts, function (i) {
72984                return i != null;
72985            });
72986            var isNowValid = !isNaN(m._d.getTime()) &&
72987                flags.overflow < 0 &&
72988                !flags.empty &&
72989                !flags.invalidMonth &&
72990                !flags.invalidWeekday &&
72991                !flags.weekdayMismatch &&
72992                !flags.nullInput &&
72993                !flags.invalidFormat &&
72994                !flags.userInvalidated &&
72995                (!flags.meridiem || (flags.meridiem && parsedParts));
72996
72997            if (m._strict) {
72998                isNowValid = isNowValid &&
72999                    flags.charsLeftOver === 0 &&
73000                    flags.unusedTokens.length === 0 &&
73001                    flags.bigHour === undefined;
73002            }
73003
73004            if (Object.isFrozen == null || !Object.isFrozen(m)) {
73005                m._isValid = isNowValid;
73006            }
73007            else {
73008                return isNowValid;
73009            }
73010        }
73011        return m._isValid;
73012    }
73013
73014    function createInvalid (flags) {
73015        var m = createUTC(NaN);
73016        if (flags != null) {
73017            extend(getParsingFlags(m), flags);
73018        }
73019        else {
73020            getParsingFlags(m).userInvalidated = true;
73021        }
73022
73023        return m;
73024    }
73025
73026    // Plugins that add properties should also add the key here (null value),
73027    // so we can properly clone ourselves.
73028    var momentProperties = hooks.momentProperties = [];
73029
73030    function copyConfig(to, from) {
73031        var i, prop, val;
73032
73033        if (!isUndefined(from._isAMomentObject)) {
73034            to._isAMomentObject = from._isAMomentObject;
73035        }
73036        if (!isUndefined(from._i)) {
73037            to._i = from._i;
73038        }
73039        if (!isUndefined(from._f)) {
73040            to._f = from._f;
73041        }
73042        if (!isUndefined(from._l)) {
73043            to._l = from._l;
73044        }
73045        if (!isUndefined(from._strict)) {
73046            to._strict = from._strict;
73047        }
73048        if (!isUndefined(from._tzm)) {
73049            to._tzm = from._tzm;
73050        }
73051        if (!isUndefined(from._isUTC)) {
73052            to._isUTC = from._isUTC;
73053        }
73054        if (!isUndefined(from._offset)) {
73055            to._offset = from._offset;
73056        }
73057        if (!isUndefined(from._pf)) {
73058            to._pf = getParsingFlags(from);
73059        }
73060        if (!isUndefined(from._locale)) {
73061            to._locale = from._locale;
73062        }
73063
73064        if (momentProperties.length > 0) {
73065            for (i = 0; i < momentProperties.length; i++) {
73066                prop = momentProperties[i];
73067                val = from[prop];
73068                if (!isUndefined(val)) {
73069                    to[prop] = val;
73070                }
73071            }
73072        }
73073
73074        return to;
73075    }
73076
73077    var updateInProgress = false;
73078
73079    // Moment prototype object
73080    function Moment(config) {
73081        copyConfig(this, config);
73082        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
73083        if (!this.isValid()) {
73084            this._d = new Date(NaN);
73085        }
73086        // Prevent infinite loop in case updateOffset creates new moment
73087        // objects.
73088        if (updateInProgress === false) {
73089            updateInProgress = true;
73090            hooks.updateOffset(this);
73091            updateInProgress = false;
73092        }
73093    }
73094
73095    function isMoment (obj) {
73096        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
73097    }
73098
73099    function absFloor (number) {
73100        if (number < 0) {
73101            // -0 -> 0
73102            return Math.ceil(number) || 0;
73103        } else {
73104            return Math.floor(number);
73105        }
73106    }
73107
73108    function toInt(argumentForCoercion) {
73109        var coercedNumber = +argumentForCoercion,
73110            value = 0;
73111
73112        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
73113            value = absFloor(coercedNumber);
73114        }
73115
73116        return value;
73117    }
73118
73119    // compare two arrays, return the number of differences
73120    function compareArrays(array1, array2, dontConvert) {
73121        var len = Math.min(array1.length, array2.length),
73122            lengthDiff = Math.abs(array1.length - array2.length),
73123            diffs = 0,
73124            i;
73125        for (i = 0; i < len; i++) {
73126            if ((dontConvert && array1[i] !== array2[i]) ||
73127                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
73128                diffs++;
73129            }
73130        }
73131        return diffs + lengthDiff;
73132    }
73133
73134    function warn(msg) {
73135        if (hooks.suppressDeprecationWarnings === false &&
73136                (typeof console !==  'undefined') && console.warn) {
73137            console.warn('Deprecation warning: ' + msg);
73138        }
73139    }
73140
73141    function deprecate(msg, fn) {
73142        var firstTime = true;
73143
73144        return extend(function () {
73145            if (hooks.deprecationHandler != null) {
73146                hooks.deprecationHandler(null, msg);
73147            }
73148            if (firstTime) {
73149                var args = [];
73150                var arg;
73151                for (var i = 0; i < arguments.length; i++) {
73152                    arg = '';
73153                    if (typeof arguments[i] === 'object') {
73154                        arg += '\n[' + i + '] ';
73155                        for (var key in arguments[0]) {
73156                            arg += key + ': ' + arguments[0][key] + ', ';
73157                        }
73158                        arg = arg.slice(0, -2); // Remove trailing comma and space
73159                    } else {
73160                        arg = arguments[i];
73161                    }
73162                    args.push(arg);
73163                }
73164                warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
73165                firstTime = false;
73166            }
73167            return fn.apply(this, arguments);
73168        }, fn);
73169    }
73170
73171    var deprecations = {};
73172
73173    function deprecateSimple(name, msg) {
73174        if (hooks.deprecationHandler != null) {
73175            hooks.deprecationHandler(name, msg);
73176        }
73177        if (!deprecations[name]) {
73178            warn(msg);
73179            deprecations[name] = true;
73180        }
73181    }
73182
73183    hooks.suppressDeprecationWarnings = false;
73184    hooks.deprecationHandler = null;
73185
73186    function isFunction(input) {
73187        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
73188    }
73189
73190    function set (config) {
73191        var prop, i;
73192        for (i in config) {
73193            prop = config[i];
73194            if (isFunction(prop)) {
73195                this[i] = prop;
73196            } else {
73197                this['_' + i] = prop;
73198            }
73199        }
73200        this._config = config;
73201        // Lenient ordinal parsing accepts just a number in addition to
73202        // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
73203        // TODO: Remove "ordinalParse" fallback in next major release.
73204        this._dayOfMonthOrdinalParseLenient = new RegExp(
73205            (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
73206                '|' + (/\d{1,2}/).source);
73207    }
73208
73209    function mergeConfigs(parentConfig, childConfig) {
73210        var res = extend({}, parentConfig), prop;
73211        for (prop in childConfig) {
73212            if (hasOwnProp(childConfig, prop)) {
73213                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
73214                    res[prop] = {};
73215                    extend(res[prop], parentConfig[prop]);
73216                    extend(res[prop], childConfig[prop]);
73217                } else if (childConfig[prop] != null) {
73218                    res[prop] = childConfig[prop];
73219                } else {
73220                    delete res[prop];
73221                }
73222            }
73223        }
73224        for (prop in parentConfig) {
73225            if (hasOwnProp(parentConfig, prop) &&
73226                    !hasOwnProp(childConfig, prop) &&
73227                    isObject(parentConfig[prop])) {
73228                // make sure changes to properties don't modify parent config
73229                res[prop] = extend({}, res[prop]);
73230            }
73231        }
73232        return res;
73233    }
73234
73235    function Locale(config) {
73236        if (config != null) {
73237            this.set(config);
73238        }
73239    }
73240
73241    var keys;
73242
73243    if (Object.keys) {
73244        keys = Object.keys;
73245    } else {
73246        keys = function (obj) {
73247            var i, res = [];
73248            for (i in obj) {
73249                if (hasOwnProp(obj, i)) {
73250                    res.push(i);
73251                }
73252            }
73253            return res;
73254        };
73255    }
73256
73257    var defaultCalendar = {
73258        sameDay : '[Today at] LT',
73259        nextDay : '[Tomorrow at] LT',
73260        nextWeek : 'dddd [at] LT',
73261        lastDay : '[Yesterday at] LT',
73262        lastWeek : '[Last] dddd [at] LT',
73263        sameElse : 'L'
73264    };
73265
73266    function calendar (key, mom, now) {
73267        var output = this._calendar[key] || this._calendar['sameElse'];
73268        return isFunction(output) ? output.call(mom, now) : output;
73269    }
73270
73271    var defaultLongDateFormat = {
73272        LTS  : 'h:mm:ss A',
73273        LT   : 'h:mm A',
73274        L    : 'MM/DD/YYYY',
73275        LL   : 'MMMM D, YYYY',
73276        LLL  : 'MMMM D, YYYY h:mm A',
73277        LLLL : 'dddd, MMMM D, YYYY h:mm A'
73278    };
73279
73280    function longDateFormat (key) {
73281        var format = this._longDateFormat[key],
73282            formatUpper = this._longDateFormat[key.toUpperCase()];
73283
73284        if (format || !formatUpper) {
73285            return format;
73286        }
73287
73288        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
73289            return val.slice(1);
73290        });
73291
73292        return this._longDateFormat[key];
73293    }
73294
73295    var defaultInvalidDate = 'Invalid date';
73296
73297    function invalidDate () {
73298        return this._invalidDate;
73299    }
73300
73301    var defaultOrdinal = '%d';
73302    var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
73303
73304    function ordinal (number) {
73305        return this._ordinal.replace('%d', number);
73306    }
73307
73308    var defaultRelativeTime = {
73309        future : 'in %s',
73310        past   : '%s ago',
73311        s  : 'a few seconds',
73312        ss : '%d seconds',
73313        m  : 'a minute',
73314        mm : '%d minutes',
73315        h  : 'an hour',
73316        hh : '%d hours',
73317        d  : 'a day',
73318        dd : '%d days',
73319        M  : 'a month',
73320        MM : '%d months',
73321        y  : 'a year',
73322        yy : '%d years'
73323    };
73324
73325    function relativeTime (number, withoutSuffix, string, isFuture) {
73326        var output = this._relativeTime[string];
73327        return (isFunction(output)) ?
73328            output(number, withoutSuffix, string, isFuture) :
73329            output.replace(/%d/i, number);
73330    }
73331
73332    function pastFuture (diff, output) {
73333        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
73334        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
73335    }
73336
73337    var aliases = {};
73338
73339    function addUnitAlias (unit, shorthand) {
73340        var lowerCase = unit.toLowerCase();
73341        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
73342    }
73343
73344    function normalizeUnits(units) {
73345        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
73346    }
73347
73348    function normalizeObjectUnits(inputObject) {
73349        var normalizedInput = {},
73350            normalizedProp,
73351            prop;
73352
73353        for (prop in inputObject) {
73354            if (hasOwnProp(inputObject, prop)) {
73355                normalizedProp = normalizeUnits(prop);
73356                if (normalizedProp) {
73357                    normalizedInput[normalizedProp] = inputObject[prop];
73358                }
73359            }
73360        }
73361
73362        return normalizedInput;
73363    }
73364
73365    var priorities = {};
73366
73367    function addUnitPriority(unit, priority) {
73368        priorities[unit] = priority;
73369    }
73370
73371    function getPrioritizedUnits(unitsObj) {
73372        var units = [];
73373        for (var u in unitsObj) {
73374            units.push({unit: u, priority: priorities[u]});
73375        }
73376        units.sort(function (a, b) {
73377            return a.priority - b.priority;
73378        });
73379        return units;
73380    }
73381
73382    function zeroFill(number, targetLength, forceSign) {
73383        var absNumber = '' + Math.abs(number),
73384            zerosToFill = targetLength - absNumber.length,
73385            sign = number >= 0;
73386        return (sign ? (forceSign ? '+' : '') : '-') +
73387            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
73388    }
73389
73390    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;
73391
73392    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
73393
73394    var formatFunctions = {};
73395
73396    var formatTokenFunctions = {};
73397
73398    // token:    'M'
73399    // padded:   ['MM', 2]
73400    // ordinal:  'Mo'
73401    // callback: function () { this.month() + 1 }
73402    function addFormatToken (token, padded, ordinal, callback) {
73403        var func = callback;
73404        if (typeof callback === 'string') {
73405            func = function () {
73406                return this[callback]();
73407            };
73408        }
73409        if (token) {
73410            formatTokenFunctions[token] = func;
73411        }
73412        if (padded) {
73413            formatTokenFunctions[padded[0]] = function () {
73414                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
73415            };
73416        }
73417        if (ordinal) {
73418            formatTokenFunctions[ordinal] = function () {
73419                return this.localeData().ordinal(func.apply(this, arguments), token);
73420            };
73421        }
73422    }
73423
73424    function removeFormattingTokens(input) {
73425        if (input.match(/\[[\s\S]/)) {
73426            return input.replace(/^\[|\]$/g, '');
73427        }
73428        return input.replace(/\\/g, '');
73429    }
73430
73431    function makeFormatFunction(format) {
73432        var array = format.match(formattingTokens), i, length;
73433
73434        for (i = 0, length = array.length; i < length; i++) {
73435            if (formatTokenFunctions[array[i]]) {
73436                array[i] = formatTokenFunctions[array[i]];
73437            } else {
73438                array[i] = removeFormattingTokens(array[i]);
73439            }
73440        }
73441
73442        return function (mom) {
73443            var output = '', i;
73444            for (i = 0; i < length; i++) {
73445                output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
73446            }
73447            return output;
73448        };
73449    }
73450
73451    // format date using native date object
73452    function formatMoment(m, format) {
73453        if (!m.isValid()) {
73454            return m.localeData().invalidDate();
73455        }
73456
73457        format = expandFormat(format, m.localeData());
73458        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
73459
73460        return formatFunctions[format](m);
73461    }
73462
73463    function expandFormat(format, locale) {
73464        var i = 5;
73465
73466        function replaceLongDateFormatTokens(input) {
73467            return locale.longDateFormat(input) || input;
73468        }
73469
73470        localFormattingTokens.lastIndex = 0;
73471        while (i >= 0 && localFormattingTokens.test(format)) {
73472            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
73473            localFormattingTokens.lastIndex = 0;
73474            i -= 1;
73475        }
73476
73477        return format;
73478    }
73479
73480    var match1         = /\d/;            //       0 - 9
73481    var match2         = /\d\d/;          //      00 - 99
73482    var match3         = /\d{3}/;         //     000 - 999
73483    var match4         = /\d{4}/;         //    0000 - 9999
73484    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
73485    var match1to2      = /\d\d?/;         //       0 - 99
73486    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
73487    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
73488    var match1to3      = /\d{1,3}/;       //       0 - 999
73489    var match1to4      = /\d{1,4}/;       //       0 - 9999
73490    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
73491
73492    var matchUnsigned  = /\d+/;           //       0 - inf
73493    var matchSigned    = /[+-]?\d+/;      //    -inf - inf
73494
73495    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
73496    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
73497
73498    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
73499
73500    // any word (or two) characters or numbers including two/three word month in arabic.
73501    // includes scottish gaelic two word and hyphenated months
73502    var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
73503
73504    var regexes = {};
73505
73506    function addRegexToken (token, regex, strictRegex) {
73507        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
73508            return (isStrict && strictRegex) ? strictRegex : regex;
73509        };
73510    }
73511
73512    function getParseRegexForToken (token, config) {
73513        if (!hasOwnProp(regexes, token)) {
73514            return new RegExp(unescapeFormat(token));
73515        }
73516
73517        return regexes[token](config._strict, config._locale);
73518    }
73519
73520    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
73521    function unescapeFormat(s) {
73522        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
73523            return p1 || p2 || p3 || p4;
73524        }));
73525    }
73526
73527    function regexEscape(s) {
73528        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
73529    }
73530
73531    var tokens = {};
73532
73533    function addParseToken (token, callback) {
73534        var i, func = callback;
73535        if (typeof token === 'string') {
73536            token = [token];
73537        }
73538        if (isNumber(callback)) {
73539            func = function (input, array) {
73540                array[callback] = toInt(input);
73541            };
73542        }
73543        for (i = 0; i < token.length; i++) {
73544            tokens[token[i]] = func;
73545        }
73546    }
73547
73548    function addWeekParseToken (token, callback) {
73549        addParseToken(token, function (input, array, config, token) {
73550            config._w = config._w || {};
73551            callback(input, config._w, config, token);
73552        });
73553    }
73554
73555    function addTimeToArrayFromToken(token, input, config) {
73556        if (input != null && hasOwnProp(tokens, token)) {
73557            tokens[token](input, config._a, config, token);
73558        }
73559    }
73560
73561    var YEAR = 0;
73562    var MONTH = 1;
73563    var DATE = 2;
73564    var HOUR = 3;
73565    var MINUTE = 4;
73566    var SECOND = 5;
73567    var MILLISECOND = 6;
73568    var WEEK = 7;
73569    var WEEKDAY = 8;
73570
73571    // FORMATTING
73572
73573    addFormatToken('Y', 0, 0, function () {
73574        var y = this.year();
73575        return y <= 9999 ? '' + y : '+' + y;
73576    });
73577
73578    addFormatToken(0, ['YY', 2], 0, function () {
73579        return this.year() % 100;
73580    });
73581
73582    addFormatToken(0, ['YYYY',   4],       0, 'year');
73583    addFormatToken(0, ['YYYYY',  5],       0, 'year');
73584    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
73585
73586    // ALIASES
73587
73588    addUnitAlias('year', 'y');
73589
73590    // PRIORITIES
73591
73592    addUnitPriority('year', 1);
73593
73594    // PARSING
73595
73596    addRegexToken('Y',      matchSigned);
73597    addRegexToken('YY',     match1to2, match2);
73598    addRegexToken('YYYY',   match1to4, match4);
73599    addRegexToken('YYYYY',  match1to6, match6);
73600    addRegexToken('YYYYYY', match1to6, match6);
73601
73602    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
73603    addParseToken('YYYY', function (input, array) {
73604        array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
73605    });
73606    addParseToken('YY', function (input, array) {
73607        array[YEAR] = hooks.parseTwoDigitYear(input);
73608    });
73609    addParseToken('Y', function (input, array) {
73610        array[YEAR] = parseInt(input, 10);
73611    });
73612
73613    // HELPERS
73614
73615    function daysInYear(year) {
73616        return isLeapYear(year) ? 366 : 365;
73617    }
73618
73619    function isLeapYear(year) {
73620        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
73621    }
73622
73623    // HOOKS
73624
73625    hooks.parseTwoDigitYear = function (input) {
73626        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
73627    };
73628
73629    // MOMENTS
73630
73631    var getSetYear = makeGetSet('FullYear', true);
73632
73633    function getIsLeapYear () {
73634        return isLeapYear(this.year());
73635    }
73636
73637    function makeGetSet (unit, keepTime) {
73638        return function (value) {
73639            if (value != null) {
73640                set$1(this, unit, value);
73641                hooks.updateOffset(this, keepTime);
73642                return this;
73643            } else {
73644                return get(this, unit);
73645            }
73646        };
73647    }
73648
73649    function get (mom, unit) {
73650        return mom.isValid() ?
73651            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
73652    }
73653
73654    function set$1 (mom, unit, value) {
73655        if (mom.isValid() && !isNaN(value)) {
73656            if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
73657                mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
73658            }
73659            else {
73660                mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
73661            }
73662        }
73663    }
73664
73665    // MOMENTS
73666
73667    function stringGet (units) {
73668        units = normalizeUnits(units);
73669        if (isFunction(this[units])) {
73670            return this[units]();
73671        }
73672        return this;
73673    }
73674
73675
73676    function stringSet (units, value) {
73677        if (typeof units === 'object') {
73678            units = normalizeObjectUnits(units);
73679            var prioritized = getPrioritizedUnits(units);
73680            for (var i = 0; i < prioritized.length; i++) {
73681                this[prioritized[i].unit](units[prioritized[i].unit]);
73682            }
73683        } else {
73684            units = normalizeUnits(units);
73685            if (isFunction(this[units])) {
73686                return this[units](value);
73687            }
73688        }
73689        return this;
73690    }
73691
73692    function mod(n, x) {
73693        return ((n % x) + x) % x;
73694    }
73695
73696    var indexOf;
73697
73698    if (Array.prototype.indexOf) {
73699        indexOf = Array.prototype.indexOf;
73700    } else {
73701        indexOf = function (o) {
73702            // I know
73703            var i;
73704            for (i = 0; i < this.length; ++i) {
73705                if (this[i] === o) {
73706                    return i;
73707                }
73708            }
73709            return -1;
73710        };
73711    }
73712
73713    function daysInMonth(year, month) {
73714        if (isNaN(year) || isNaN(month)) {
73715            return NaN;
73716        }
73717        var modMonth = mod(month, 12);
73718        year += (month - modMonth) / 12;
73719        return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
73720    }
73721
73722    // FORMATTING
73723
73724    addFormatToken('M', ['MM', 2], 'Mo', function () {
73725        return this.month() + 1;
73726    });
73727
73728    addFormatToken('MMM', 0, 0, function (format) {
73729        return this.localeData().monthsShort(this, format);
73730    });
73731
73732    addFormatToken('MMMM', 0, 0, function (format) {
73733        return this.localeData().months(this, format);
73734    });
73735
73736    // ALIASES
73737
73738    addUnitAlias('month', 'M');
73739
73740    // PRIORITY
73741
73742    addUnitPriority('month', 8);
73743
73744    // PARSING
73745
73746    addRegexToken('M',    match1to2);
73747    addRegexToken('MM',   match1to2, match2);
73748    addRegexToken('MMM',  function (isStrict, locale) {
73749        return locale.monthsShortRegex(isStrict);
73750    });
73751    addRegexToken('MMMM', function (isStrict, locale) {
73752        return locale.monthsRegex(isStrict);
73753    });
73754
73755    addParseToken(['M', 'MM'], function (input, array) {
73756        array[MONTH] = toInt(input) - 1;
73757    });
73758
73759    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
73760        var month = config._locale.monthsParse(input, token, config._strict);
73761        // if we didn't find a month name, mark the date as invalid.
73762        if (month != null) {
73763            array[MONTH] = month;
73764        } else {
73765            getParsingFlags(config).invalidMonth = input;
73766        }
73767    });
73768
73769    // LOCALES
73770
73771    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
73772    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
73773    function localeMonths (m, format) {
73774        if (!m) {
73775            return isArray(this._months) ? this._months :
73776                this._months['standalone'];
73777        }
73778        return isArray(this._months) ? this._months[m.month()] :
73779            this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
73780    }
73781
73782    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
73783    function localeMonthsShort (m, format) {
73784        if (!m) {
73785            return isArray(this._monthsShort) ? this._monthsShort :
73786                this._monthsShort['standalone'];
73787        }
73788        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
73789            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
73790    }
73791
73792    function handleStrictParse(monthName, format, strict) {
73793        var i, ii, mom, llc = monthName.toLocaleLowerCase();
73794        if (!this._monthsParse) {
73795            // this is not used
73796            this._monthsParse = [];
73797            this._longMonthsParse = [];
73798            this._shortMonthsParse = [];
73799            for (i = 0; i < 12; ++i) {
73800                mom = createUTC([2000, i]);
73801                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
73802                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
73803            }
73804        }
73805
73806        if (strict) {
73807            if (format === 'MMM') {
73808                ii = indexOf.call(this._shortMonthsParse, llc);
73809                return ii !== -1 ? ii : null;
73810            } else {
73811                ii = indexOf.call(this._longMonthsParse, llc);
73812                return ii !== -1 ? ii : null;
73813            }
73814        } else {
73815            if (format === 'MMM') {
73816                ii = indexOf.call(this._shortMonthsParse, llc);
73817                if (ii !== -1) {
73818                    return ii;
73819                }
73820                ii = indexOf.call(this._longMonthsParse, llc);
73821                return ii !== -1 ? ii : null;
73822            } else {
73823                ii = indexOf.call(this._longMonthsParse, llc);
73824                if (ii !== -1) {
73825                    return ii;
73826                }
73827                ii = indexOf.call(this._shortMonthsParse, llc);
73828                return ii !== -1 ? ii : null;
73829            }
73830        }
73831    }
73832
73833    function localeMonthsParse (monthName, format, strict) {
73834        var i, mom, regex;
73835
73836        if (this._monthsParseExact) {
73837            return handleStrictParse.call(this, monthName, format, strict);
73838        }
73839
73840        if (!this._monthsParse) {
73841            this._monthsParse = [];
73842            this._longMonthsParse = [];
73843            this._shortMonthsParse = [];
73844        }
73845
73846        // TODO: add sorting
73847        // Sorting makes sure if one month (or abbr) is a prefix of another
73848        // see sorting in computeMonthsParse
73849        for (i = 0; i < 12; i++) {
73850            // make the regex if we don't have it already
73851            mom = createUTC([2000, i]);
73852            if (strict && !this._longMonthsParse[i]) {
73853                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
73854                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
73855            }
73856            if (!strict && !this._monthsParse[i]) {
73857                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
73858                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
73859            }
73860            // test the regex
73861            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
73862                return i;
73863            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
73864                return i;
73865            } else if (!strict && this._monthsParse[i].test(monthName)) {
73866                return i;
73867            }
73868        }
73869    }
73870
73871    // MOMENTS
73872
73873    function setMonth (mom, value) {
73874        var dayOfMonth;
73875
73876        if (!mom.isValid()) {
73877            // No op
73878            return mom;
73879        }
73880
73881        if (typeof value === 'string') {
73882            if (/^\d+$/.test(value)) {
73883                value = toInt(value);
73884            } else {
73885                value = mom.localeData().monthsParse(value);
73886                // TODO: Another silent failure?
73887                if (!isNumber(value)) {
73888                    return mom;
73889                }
73890            }
73891        }
73892
73893        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
73894        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
73895        return mom;
73896    }
73897
73898    function getSetMonth (value) {
73899        if (value != null) {
73900            setMonth(this, value);
73901            hooks.updateOffset(this, true);
73902            return this;
73903        } else {
73904            return get(this, 'Month');
73905        }
73906    }
73907
73908    function getDaysInMonth () {
73909        return daysInMonth(this.year(), this.month());
73910    }
73911
73912    var defaultMonthsShortRegex = matchWord;
73913    function monthsShortRegex (isStrict) {
73914        if (this._monthsParseExact) {
73915            if (!hasOwnProp(this, '_monthsRegex')) {
73916                computeMonthsParse.call(this);
73917            }
73918            if (isStrict) {
73919                return this._monthsShortStrictRegex;
73920            } else {
73921                return this._monthsShortRegex;
73922            }
73923        } else {
73924            if (!hasOwnProp(this, '_monthsShortRegex')) {
73925                this._monthsShortRegex = defaultMonthsShortRegex;
73926            }
73927            return this._monthsShortStrictRegex && isStrict ?
73928                this._monthsShortStrictRegex : this._monthsShortRegex;
73929        }
73930    }
73931
73932    var defaultMonthsRegex = matchWord;
73933    function monthsRegex (isStrict) {
73934        if (this._monthsParseExact) {
73935            if (!hasOwnProp(this, '_monthsRegex')) {
73936                computeMonthsParse.call(this);
73937            }
73938            if (isStrict) {
73939                return this._monthsStrictRegex;
73940            } else {
73941                return this._monthsRegex;
73942            }
73943        } else {
73944            if (!hasOwnProp(this, '_monthsRegex')) {
73945                this._monthsRegex = defaultMonthsRegex;
73946            }
73947            return this._monthsStrictRegex && isStrict ?
73948                this._monthsStrictRegex : this._monthsRegex;
73949        }
73950    }
73951
73952    function computeMonthsParse () {
73953        function cmpLenRev(a, b) {
73954            return b.length - a.length;
73955        }
73956
73957        var shortPieces = [], longPieces = [], mixedPieces = [],
73958            i, mom;
73959        for (i = 0; i < 12; i++) {
73960            // make the regex if we don't have it already
73961            mom = createUTC([2000, i]);
73962            shortPieces.push(this.monthsShort(mom, ''));
73963            longPieces.push(this.months(mom, ''));
73964            mixedPieces.push(this.months(mom, ''));
73965            mixedPieces.push(this.monthsShort(mom, ''));
73966        }
73967        // Sorting makes sure if one month (or abbr) is a prefix of another it
73968        // will match the longer piece.
73969        shortPieces.sort(cmpLenRev);
73970        longPieces.sort(cmpLenRev);
73971        mixedPieces.sort(cmpLenRev);
73972        for (i = 0; i < 12; i++) {
73973            shortPieces[i] = regexEscape(shortPieces[i]);
73974            longPieces[i] = regexEscape(longPieces[i]);
73975        }
73976        for (i = 0; i < 24; i++) {
73977            mixedPieces[i] = regexEscape(mixedPieces[i]);
73978        }
73979
73980        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
73981        this._monthsShortRegex = this._monthsRegex;
73982        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
73983        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
73984    }
73985
73986    function createDate (y, m, d, h, M, s, ms) {
73987        // can't just apply() to create a date:
73988        // https://stackoverflow.com/q/181348
73989        var date;
73990        // the date constructor remaps years 0-99 to 1900-1999
73991        if (y < 100 && y >= 0) {
73992            // preserve leap years using a full 400 year cycle, then reset
73993            date = new Date(y + 400, m, d, h, M, s, ms);
73994            if (isFinite(date.getFullYear())) {
73995                date.setFullYear(y);
73996            }
73997        } else {
73998            date = new Date(y, m, d, h, M, s, ms);
73999        }
74000
74001        return date;
74002    }
74003
74004    function createUTCDate (y) {
74005        var date;
74006        // the Date.UTC function remaps years 0-99 to 1900-1999
74007        if (y < 100 && y >= 0) {
74008            var args = Array.prototype.slice.call(arguments);
74009            // preserve leap years using a full 400 year cycle, then reset
74010            args[0] = y + 400;
74011            date = new Date(Date.UTC.apply(null, args));
74012            if (isFinite(date.getUTCFullYear())) {
74013                date.setUTCFullYear(y);
74014            }
74015        } else {
74016            date = new Date(Date.UTC.apply(null, arguments));
74017        }
74018
74019        return date;
74020    }
74021
74022    // start-of-first-week - start-of-year
74023    function firstWeekOffset(year, dow, doy) {
74024        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
74025            fwd = 7 + dow - doy,
74026            // first-week day local weekday -- which local weekday is fwd
74027            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
74028
74029        return -fwdlw + fwd - 1;
74030    }
74031
74032    // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
74033    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
74034        var localWeekday = (7 + weekday - dow) % 7,
74035            weekOffset = firstWeekOffset(year, dow, doy),
74036            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
74037            resYear, resDayOfYear;
74038
74039        if (dayOfYear <= 0) {
74040            resYear = year - 1;
74041            resDayOfYear = daysInYear(resYear) + dayOfYear;
74042        } else if (dayOfYear > daysInYear(year)) {
74043            resYear = year + 1;
74044            resDayOfYear = dayOfYear - daysInYear(year);
74045        } else {
74046            resYear = year;
74047            resDayOfYear = dayOfYear;
74048        }
74049
74050        return {
74051            year: resYear,
74052            dayOfYear: resDayOfYear
74053        };
74054    }
74055
74056    function weekOfYear(mom, dow, doy) {
74057        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
74058            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
74059            resWeek, resYear;
74060
74061        if (week < 1) {
74062            resYear = mom.year() - 1;
74063            resWeek = week + weeksInYear(resYear, dow, doy);
74064        } else if (week > weeksInYear(mom.year(), dow, doy)) {
74065            resWeek = week - weeksInYear(mom.year(), dow, doy);
74066            resYear = mom.year() + 1;
74067        } else {
74068            resYear = mom.year();
74069            resWeek = week;
74070        }
74071
74072        return {
74073            week: resWeek,
74074            year: resYear
74075        };
74076    }
74077
74078    function weeksInYear(year, dow, doy) {
74079        var weekOffset = firstWeekOffset(year, dow, doy),
74080            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
74081        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
74082    }
74083
74084    // FORMATTING
74085
74086    addFormatToken('w', ['ww', 2], 'wo', 'week');
74087    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
74088
74089    // ALIASES
74090
74091    addUnitAlias('week', 'w');
74092    addUnitAlias('isoWeek', 'W');
74093
74094    // PRIORITIES
74095
74096    addUnitPriority('week', 5);
74097    addUnitPriority('isoWeek', 5);
74098
74099    // PARSING
74100
74101    addRegexToken('w',  match1to2);
74102    addRegexToken('ww', match1to2, match2);
74103    addRegexToken('W',  match1to2);
74104    addRegexToken('WW', match1to2, match2);
74105
74106    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
74107        week[token.substr(0, 1)] = toInt(input);
74108    });
74109
74110    // HELPERS
74111
74112    // LOCALES
74113
74114    function localeWeek (mom) {
74115        return weekOfYear(mom, this._week.dow, this._week.doy).week;
74116    }
74117
74118    var defaultLocaleWeek = {
74119        dow : 0, // Sunday is the first day of the week.
74120        doy : 6  // The week that contains Jan 6th is the first week of the year.
74121    };
74122
74123    function localeFirstDayOfWeek () {
74124        return this._week.dow;
74125    }
74126
74127    function localeFirstDayOfYear () {
74128        return this._week.doy;
74129    }
74130
74131    // MOMENTS
74132
74133    function getSetWeek (input) {
74134        var week = this.localeData().week(this);
74135        return input == null ? week : this.add((input - week) * 7, 'd');
74136    }
74137
74138    function getSetISOWeek (input) {
74139        var week = weekOfYear(this, 1, 4).week;
74140        return input == null ? week : this.add((input - week) * 7, 'd');
74141    }
74142
74143    // FORMATTING
74144
74145    addFormatToken('d', 0, 'do', 'day');
74146
74147    addFormatToken('dd', 0, 0, function (format) {
74148        return this.localeData().weekdaysMin(this, format);
74149    });
74150
74151    addFormatToken('ddd', 0, 0, function (format) {
74152        return this.localeData().weekdaysShort(this, format);
74153    });
74154
74155    addFormatToken('dddd', 0, 0, function (format) {
74156        return this.localeData().weekdays(this, format);
74157    });
74158
74159    addFormatToken('e', 0, 0, 'weekday');
74160    addFormatToken('E', 0, 0, 'isoWeekday');
74161
74162    // ALIASES
74163
74164    addUnitAlias('day', 'd');
74165    addUnitAlias('weekday', 'e');
74166    addUnitAlias('isoWeekday', 'E');
74167
74168    // PRIORITY
74169    addUnitPriority('day', 11);
74170    addUnitPriority('weekday', 11);
74171    addUnitPriority('isoWeekday', 11);
74172
74173    // PARSING
74174
74175    addRegexToken('d',    match1to2);
74176    addRegexToken('e',    match1to2);
74177    addRegexToken('E',    match1to2);
74178    addRegexToken('dd',   function (isStrict, locale) {
74179        return locale.weekdaysMinRegex(isStrict);
74180    });
74181    addRegexToken('ddd',   function (isStrict, locale) {
74182        return locale.weekdaysShortRegex(isStrict);
74183    });
74184    addRegexToken('dddd',   function (isStrict, locale) {
74185        return locale.weekdaysRegex(isStrict);
74186    });
74187
74188    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
74189        var weekday = config._locale.weekdaysParse(input, token, config._strict);
74190        // if we didn't get a weekday name, mark the date as invalid
74191        if (weekday != null) {
74192            week.d = weekday;
74193        } else {
74194            getParsingFlags(config).invalidWeekday = input;
74195        }
74196    });
74197
74198    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
74199        week[token] = toInt(input);
74200    });
74201
74202    // HELPERS
74203
74204    function parseWeekday(input, locale) {
74205        if (typeof input !== 'string') {
74206            return input;
74207        }
74208
74209        if (!isNaN(input)) {
74210            return parseInt(input, 10);
74211        }
74212
74213        input = locale.weekdaysParse(input);
74214        if (typeof input === 'number') {
74215            return input;
74216        }
74217
74218        return null;
74219    }
74220
74221    function parseIsoWeekday(input, locale) {
74222        if (typeof input === 'string') {
74223            return locale.weekdaysParse(input) % 7 || 7;
74224        }
74225        return isNaN(input) ? null : input;
74226    }
74227
74228    // LOCALES
74229    function shiftWeekdays (ws, n) {
74230        return ws.slice(n, 7).concat(ws.slice(0, n));
74231    }
74232
74233    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
74234    function localeWeekdays (m, format) {
74235        var weekdays = isArray(this._weekdays) ? this._weekdays :
74236            this._weekdays[(m && m !== true && this._weekdays.isFormat.test(format)) ? 'format' : 'standalone'];
74237        return (m === true) ? shiftWeekdays(weekdays, this._week.dow)
74238            : (m) ? weekdays[m.day()] : weekdays;
74239    }
74240
74241    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
74242    function localeWeekdaysShort (m) {
74243        return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow)
74244            : (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
74245    }
74246
74247    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
74248    function localeWeekdaysMin (m) {
74249        return (m === true) ? shiftWeekdays(this._weekdaysMin, this._week.dow)
74250            : (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
74251    }
74252
74253    function handleStrictParse$1(weekdayName, format, strict) {
74254        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
74255        if (!this._weekdaysParse) {
74256            this._weekdaysParse = [];
74257            this._shortWeekdaysParse = [];
74258            this._minWeekdaysParse = [];
74259
74260            for (i = 0; i < 7; ++i) {
74261                mom = createUTC([2000, 1]).day(i);
74262                this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
74263                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
74264                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
74265            }
74266        }
74267
74268        if (strict) {
74269            if (format === 'dddd') {
74270                ii = indexOf.call(this._weekdaysParse, llc);
74271                return ii !== -1 ? ii : null;
74272            } else if (format === 'ddd') {
74273                ii = indexOf.call(this._shortWeekdaysParse, llc);
74274                return ii !== -1 ? ii : null;
74275            } else {
74276                ii = indexOf.call(this._minWeekdaysParse, llc);
74277                return ii !== -1 ? ii : null;
74278            }
74279        } else {
74280            if (format === 'dddd') {
74281                ii = indexOf.call(this._weekdaysParse, llc);
74282                if (ii !== -1) {
74283                    return ii;
74284                }
74285                ii = indexOf.call(this._shortWeekdaysParse, llc);
74286                if (ii !== -1) {
74287                    return ii;
74288                }
74289                ii = indexOf.call(this._minWeekdaysParse, llc);
74290                return ii !== -1 ? ii : null;
74291            } else if (format === 'ddd') {
74292                ii = indexOf.call(this._shortWeekdaysParse, llc);
74293                if (ii !== -1) {
74294                    return ii;
74295                }
74296                ii = indexOf.call(this._weekdaysParse, llc);
74297                if (ii !== -1) {
74298                    return ii;
74299                }
74300                ii = indexOf.call(this._minWeekdaysParse, llc);
74301                return ii !== -1 ? ii : null;
74302            } else {
74303                ii = indexOf.call(this._minWeekdaysParse, llc);
74304                if (ii !== -1) {
74305                    return ii;
74306                }
74307                ii = indexOf.call(this._weekdaysParse, llc);
74308                if (ii !== -1) {
74309                    return ii;
74310                }
74311                ii = indexOf.call(this._shortWeekdaysParse, llc);
74312                return ii !== -1 ? ii : null;
74313            }
74314        }
74315    }
74316
74317    function localeWeekdaysParse (weekdayName, format, strict) {
74318        var i, mom, regex;
74319
74320        if (this._weekdaysParseExact) {
74321            return handleStrictParse$1.call(this, weekdayName, format, strict);
74322        }
74323
74324        if (!this._weekdaysParse) {
74325            this._weekdaysParse = [];
74326            this._minWeekdaysParse = [];
74327            this._shortWeekdaysParse = [];
74328            this._fullWeekdaysParse = [];
74329        }
74330
74331        for (i = 0; i < 7; i++) {
74332            // make the regex if we don't have it already
74333
74334            mom = createUTC([2000, 1]).day(i);
74335            if (strict && !this._fullWeekdaysParse[i]) {
74336                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i');
74337                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i');
74338                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i');
74339            }
74340            if (!this._weekdaysParse[i]) {
74341                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
74342                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
74343            }
74344            // test the regex
74345            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
74346                return i;
74347            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
74348                return i;
74349            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
74350                return i;
74351            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
74352                return i;
74353            }
74354        }
74355    }
74356
74357    // MOMENTS
74358
74359    function getSetDayOfWeek (input) {
74360        if (!this.isValid()) {
74361            return input != null ? this : NaN;
74362        }
74363        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
74364        if (input != null) {
74365            input = parseWeekday(input, this.localeData());
74366            return this.add(input - day, 'd');
74367        } else {
74368            return day;
74369        }
74370    }
74371
74372    function getSetLocaleDayOfWeek (input) {
74373        if (!this.isValid()) {
74374            return input != null ? this : NaN;
74375        }
74376        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
74377        return input == null ? weekday : this.add(input - weekday, 'd');
74378    }
74379
74380    function getSetISODayOfWeek (input) {
74381        if (!this.isValid()) {
74382            return input != null ? this : NaN;
74383        }
74384
74385        // behaves the same as moment#day except
74386        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
74387        // as a setter, sunday should belong to the previous week.
74388
74389        if (input != null) {
74390            var weekday = parseIsoWeekday(input, this.localeData());
74391            return this.day(this.day() % 7 ? weekday : weekday - 7);
74392        } else {
74393            return this.day() || 7;
74394        }
74395    }
74396
74397    var defaultWeekdaysRegex = matchWord;
74398    function weekdaysRegex (isStrict) {
74399        if (this._weekdaysParseExact) {
74400            if (!hasOwnProp(this, '_weekdaysRegex')) {
74401                computeWeekdaysParse.call(this);
74402            }
74403            if (isStrict) {
74404                return this._weekdaysStrictRegex;
74405            } else {
74406                return this._weekdaysRegex;
74407            }
74408        } else {
74409            if (!hasOwnProp(this, '_weekdaysRegex')) {
74410                this._weekdaysRegex = defaultWeekdaysRegex;
74411            }
74412            return this._weekdaysStrictRegex && isStrict ?
74413                this._weekdaysStrictRegex : this._weekdaysRegex;
74414        }
74415    }
74416
74417    var defaultWeekdaysShortRegex = matchWord;
74418    function weekdaysShortRegex (isStrict) {
74419        if (this._weekdaysParseExact) {
74420            if (!hasOwnProp(this, '_weekdaysRegex')) {
74421                computeWeekdaysParse.call(this);
74422            }
74423            if (isStrict) {
74424                return this._weekdaysShortStrictRegex;
74425            } else {
74426                return this._weekdaysShortRegex;
74427            }
74428        } else {
74429            if (!hasOwnProp(this, '_weekdaysShortRegex')) {
74430                this._weekdaysShortRegex = defaultWeekdaysShortRegex;
74431            }
74432            return this._weekdaysShortStrictRegex && isStrict ?
74433                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
74434        }
74435    }
74436
74437    var defaultWeekdaysMinRegex = matchWord;
74438    function weekdaysMinRegex (isStrict) {
74439        if (this._weekdaysParseExact) {
74440            if (!hasOwnProp(this, '_weekdaysRegex')) {
74441                computeWeekdaysParse.call(this);
74442            }
74443            if (isStrict) {
74444                return this._weekdaysMinStrictRegex;
74445            } else {
74446                return this._weekdaysMinRegex;
74447            }
74448        } else {
74449            if (!hasOwnProp(this, '_weekdaysMinRegex')) {
74450                this._weekdaysMinRegex = defaultWeekdaysMinRegex;
74451            }
74452            return this._weekdaysMinStrictRegex && isStrict ?
74453                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
74454        }
74455    }
74456
74457
74458    function computeWeekdaysParse () {
74459        function cmpLenRev(a, b) {
74460            return b.length - a.length;
74461        }
74462
74463        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
74464            i, mom, minp, shortp, longp;
74465        for (i = 0; i < 7; i++) {
74466            // make the regex if we don't have it already
74467            mom = createUTC([2000, 1]).day(i);
74468            minp = this.weekdaysMin(mom, '');
74469            shortp = this.weekdaysShort(mom, '');
74470            longp = this.weekdays(mom, '');
74471            minPieces.push(minp);
74472            shortPieces.push(shortp);
74473            longPieces.push(longp);
74474            mixedPieces.push(minp);
74475            mixedPieces.push(shortp);
74476            mixedPieces.push(longp);
74477        }
74478        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
74479        // will match the longer piece.
74480        minPieces.sort(cmpLenRev);
74481        shortPieces.sort(cmpLenRev);
74482        longPieces.sort(cmpLenRev);
74483        mixedPieces.sort(cmpLenRev);
74484        for (i = 0; i < 7; i++) {
74485            shortPieces[i] = regexEscape(shortPieces[i]);
74486            longPieces[i] = regexEscape(longPieces[i]);
74487            mixedPieces[i] = regexEscape(mixedPieces[i]);
74488        }
74489
74490        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
74491        this._weekdaysShortRegex = this._weekdaysRegex;
74492        this._weekdaysMinRegex = this._weekdaysRegex;
74493
74494        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
74495        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
74496        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
74497    }
74498
74499    // FORMATTING
74500
74501    function hFormat() {
74502        return this.hours() % 12 || 12;
74503    }
74504
74505    function kFormat() {
74506        return this.hours() || 24;
74507    }
74508
74509    addFormatToken('H', ['HH', 2], 0, 'hour');
74510    addFormatToken('h', ['hh', 2], 0, hFormat);
74511    addFormatToken('k', ['kk', 2], 0, kFormat);
74512
74513    addFormatToken('hmm', 0, 0, function () {
74514        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
74515    });
74516
74517    addFormatToken('hmmss', 0, 0, function () {
74518        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
74519            zeroFill(this.seconds(), 2);
74520    });
74521
74522    addFormatToken('Hmm', 0, 0, function () {
74523        return '' + this.hours() + zeroFill(this.minutes(), 2);
74524    });
74525
74526    addFormatToken('Hmmss', 0, 0, function () {
74527        return '' + this.hours() + zeroFill(this.minutes(), 2) +
74528            zeroFill(this.seconds(), 2);
74529    });
74530
74531    function meridiem (token, lowercase) {
74532        addFormatToken(token, 0, 0, function () {
74533            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
74534        });
74535    }
74536
74537    meridiem('a', true);
74538    meridiem('A', false);
74539
74540    // ALIASES
74541
74542    addUnitAlias('hour', 'h');
74543
74544    // PRIORITY
74545    addUnitPriority('hour', 13);
74546
74547    // PARSING
74548
74549    function matchMeridiem (isStrict, locale) {
74550        return locale._meridiemParse;
74551    }
74552
74553    addRegexToken('a',  matchMeridiem);
74554    addRegexToken('A',  matchMeridiem);
74555    addRegexToken('H',  match1to2);
74556    addRegexToken('h',  match1to2);
74557    addRegexToken('k',  match1to2);
74558    addRegexToken('HH', match1to2, match2);
74559    addRegexToken('hh', match1to2, match2);
74560    addRegexToken('kk', match1to2, match2);
74561
74562    addRegexToken('hmm', match3to4);
74563    addRegexToken('hmmss', match5to6);
74564    addRegexToken('Hmm', match3to4);
74565    addRegexToken('Hmmss', match5to6);
74566
74567    addParseToken(['H', 'HH'], HOUR);
74568    addParseToken(['k', 'kk'], function (input, array, config) {
74569        var kInput = toInt(input);
74570        array[HOUR] = kInput === 24 ? 0 : kInput;
74571    });
74572    addParseToken(['a', 'A'], function (input, array, config) {
74573        config._isPm = config._locale.isPM(input);
74574        config._meridiem = input;
74575    });
74576    addParseToken(['h', 'hh'], function (input, array, config) {
74577        array[HOUR] = toInt(input);
74578        getParsingFlags(config).bigHour = true;
74579    });
74580    addParseToken('hmm', function (input, array, config) {
74581        var pos = input.length - 2;
74582        array[HOUR] = toInt(input.substr(0, pos));
74583        array[MINUTE] = toInt(input.substr(pos));
74584        getParsingFlags(config).bigHour = true;
74585    });
74586    addParseToken('hmmss', function (input, array, config) {
74587        var pos1 = input.length - 4;
74588        var pos2 = input.length - 2;
74589        array[HOUR] = toInt(input.substr(0, pos1));
74590        array[MINUTE] = toInt(input.substr(pos1, 2));
74591        array[SECOND] = toInt(input.substr(pos2));
74592        getParsingFlags(config).bigHour = true;
74593    });
74594    addParseToken('Hmm', function (input, array, config) {
74595        var pos = input.length - 2;
74596        array[HOUR] = toInt(input.substr(0, pos));
74597        array[MINUTE] = toInt(input.substr(pos));
74598    });
74599    addParseToken('Hmmss', function (input, array, config) {
74600        var pos1 = input.length - 4;
74601        var pos2 = input.length - 2;
74602        array[HOUR] = toInt(input.substr(0, pos1));
74603        array[MINUTE] = toInt(input.substr(pos1, 2));
74604        array[SECOND] = toInt(input.substr(pos2));
74605    });
74606
74607    // LOCALES
74608
74609    function localeIsPM (input) {
74610        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
74611        // Using charAt should be more compatible.
74612        return ((input + '').toLowerCase().charAt(0) === 'p');
74613    }
74614
74615    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
74616    function localeMeridiem (hours, minutes, isLower) {
74617        if (hours > 11) {
74618            return isLower ? 'pm' : 'PM';
74619        } else {
74620            return isLower ? 'am' : 'AM';
74621        }
74622    }
74623
74624
74625    // MOMENTS
74626
74627    // Setting the hour should keep the time, because the user explicitly
74628    // specified which hour they want. So trying to maintain the same hour (in
74629    // a new timezone) makes sense. Adding/subtracting hours does not follow
74630    // this rule.
74631    var getSetHour = makeGetSet('Hours', true);
74632
74633    var baseConfig = {
74634        calendar: defaultCalendar,
74635        longDateFormat: defaultLongDateFormat,
74636        invalidDate: defaultInvalidDate,
74637        ordinal: defaultOrdinal,
74638        dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
74639        relativeTime: defaultRelativeTime,
74640
74641        months: defaultLocaleMonths,
74642        monthsShort: defaultLocaleMonthsShort,
74643
74644        week: defaultLocaleWeek,
74645
74646        weekdays: defaultLocaleWeekdays,
74647        weekdaysMin: defaultLocaleWeekdaysMin,
74648        weekdaysShort: defaultLocaleWeekdaysShort,
74649
74650        meridiemParse: defaultLocaleMeridiemParse
74651    };
74652
74653    // internal storage for locale config files
74654    var locales = {};
74655    var localeFamilies = {};
74656    var globalLocale;
74657
74658    function normalizeLocale(key) {
74659        return key ? key.toLowerCase().replace('_', '-') : key;
74660    }
74661
74662    // pick the locale from the array
74663    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
74664    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
74665    function chooseLocale(names) {
74666        var i = 0, j, next, locale, split;
74667
74668        while (i < names.length) {
74669            split = normalizeLocale(names[i]).split('-');
74670            j = split.length;
74671            next = normalizeLocale(names[i + 1]);
74672            next = next ? next.split('-') : null;
74673            while (j > 0) {
74674                locale = loadLocale(split.slice(0, j).join('-'));
74675                if (locale) {
74676                    return locale;
74677                }
74678                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
74679                    //the next array item is better than a shallower substring of this one
74680                    break;
74681                }
74682                j--;
74683            }
74684            i++;
74685        }
74686        return globalLocale;
74687    }
74688
74689    function loadLocale(name) {
74690        var oldLocale = null;
74691        // TODO: Find a better way to register and load all the locales in Node
74692        if (!locales[name] && ('object' !== 'undefined') &&
74693                module && module.exports) {
74694            try {
74695                oldLocale = globalLocale._abbr;
74696                var aliasedRequire = commonjsRequire;
74697                aliasedRequire('./locale/' + name);
74698                getSetGlobalLocale(oldLocale);
74699            } catch (e) {}
74700        }
74701        return locales[name];
74702    }
74703
74704    // This function will load locale and then set the global locale.  If
74705    // no arguments are passed in, it will simply return the current global
74706    // locale key.
74707    function getSetGlobalLocale (key, values) {
74708        var data;
74709        if (key) {
74710            if (isUndefined(values)) {
74711                data = getLocale(key);
74712            }
74713            else {
74714                data = defineLocale(key, values);
74715            }
74716
74717            if (data) {
74718                // moment.duration._locale = moment._locale = data;
74719                globalLocale = data;
74720            }
74721            else {
74722                if ((typeof console !==  'undefined') && console.warn) {
74723                    //warn user if arguments are passed but the locale could not be set
74724                    console.warn('Locale ' + key +  ' not found. Did you forget to load it?');
74725                }
74726            }
74727        }
74728
74729        return globalLocale._abbr;
74730    }
74731
74732    function defineLocale (name, config) {
74733        if (config !== null) {
74734            var locale, parentConfig = baseConfig;
74735            config.abbr = name;
74736            if (locales[name] != null) {
74737                deprecateSimple('defineLocaleOverride',
74738                        'use moment.updateLocale(localeName, config) to change ' +
74739                        'an existing locale. moment.defineLocale(localeName, ' +
74740                        'config) should only be used for creating a new locale ' +
74741                        'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
74742                parentConfig = locales[name]._config;
74743            } else if (config.parentLocale != null) {
74744                if (locales[config.parentLocale] != null) {
74745                    parentConfig = locales[config.parentLocale]._config;
74746                } else {
74747                    locale = loadLocale(config.parentLocale);
74748                    if (locale != null) {
74749                        parentConfig = locale._config;
74750                    } else {
74751                        if (!localeFamilies[config.parentLocale]) {
74752                            localeFamilies[config.parentLocale] = [];
74753                        }
74754                        localeFamilies[config.parentLocale].push({
74755                            name: name,
74756                            config: config
74757                        });
74758                        return null;
74759                    }
74760                }
74761            }
74762            locales[name] = new Locale(mergeConfigs(parentConfig, config));
74763
74764            if (localeFamilies[name]) {
74765                localeFamilies[name].forEach(function (x) {
74766                    defineLocale(x.name, x.config);
74767                });
74768            }
74769
74770            // backwards compat for now: also set the locale
74771            // make sure we set the locale AFTER all child locales have been
74772            // created, so we won't end up with the child locale set.
74773            getSetGlobalLocale(name);
74774
74775
74776            return locales[name];
74777        } else {
74778            // useful for testing
74779            delete locales[name];
74780            return null;
74781        }
74782    }
74783
74784    function updateLocale(name, config) {
74785        if (config != null) {
74786            var locale, tmpLocale, parentConfig = baseConfig;
74787            // MERGE
74788            tmpLocale = loadLocale(name);
74789            if (tmpLocale != null) {
74790                parentConfig = tmpLocale._config;
74791            }
74792            config = mergeConfigs(parentConfig, config);
74793            locale = new Locale(config);
74794            locale.parentLocale = locales[name];
74795            locales[name] = locale;
74796
74797            // backwards compat for now: also set the locale
74798            getSetGlobalLocale(name);
74799        } else {
74800            // pass null for config to unupdate, useful for tests
74801            if (locales[name] != null) {
74802                if (locales[name].parentLocale != null) {
74803                    locales[name] = locales[name].parentLocale;
74804                } else if (locales[name] != null) {
74805                    delete locales[name];
74806                }
74807            }
74808        }
74809        return locales[name];
74810    }
74811
74812    // returns locale data
74813    function getLocale (key) {
74814        var locale;
74815
74816        if (key && key._locale && key._locale._abbr) {
74817            key = key._locale._abbr;
74818        }
74819
74820        if (!key) {
74821            return globalLocale;
74822        }
74823
74824        if (!isArray(key)) {
74825            //short-circuit everything else
74826            locale = loadLocale(key);
74827            if (locale) {
74828                return locale;
74829            }
74830            key = [key];
74831        }
74832
74833        return chooseLocale(key);
74834    }
74835
74836    function listLocales() {
74837        return keys(locales);
74838    }
74839
74840    function checkOverflow (m) {
74841        var overflow;
74842        var a = m._a;
74843
74844        if (a && getParsingFlags(m).overflow === -2) {
74845            overflow =
74846                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
74847                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
74848                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
74849                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
74850                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
74851                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
74852                -1;
74853
74854            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
74855                overflow = DATE;
74856            }
74857            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
74858                overflow = WEEK;
74859            }
74860            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
74861                overflow = WEEKDAY;
74862            }
74863
74864            getParsingFlags(m).overflow = overflow;
74865        }
74866
74867        return m;
74868    }
74869
74870    // Pick the first defined of two or three arguments.
74871    function defaults(a, b, c) {
74872        if (a != null) {
74873            return a;
74874        }
74875        if (b != null) {
74876            return b;
74877        }
74878        return c;
74879    }
74880
74881    function currentDateArray(config) {
74882        // hooks is actually the exported moment object
74883        var nowValue = new Date(hooks.now());
74884        if (config._useUTC) {
74885            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
74886        }
74887        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
74888    }
74889
74890    // convert an array to a date.
74891    // the array should mirror the parameters below
74892    // note: all values past the year are optional and will default to the lowest possible value.
74893    // [year, month, day , hour, minute, second, millisecond]
74894    function configFromArray (config) {
74895        var i, date, input = [], currentDate, expectedWeekday, yearToUse;
74896
74897        if (config._d) {
74898            return;
74899        }
74900
74901        currentDate = currentDateArray(config);
74902
74903        //compute day of the year from weeks and weekdays
74904        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
74905            dayOfYearFromWeekInfo(config);
74906        }
74907
74908        //if the day of the year is set, figure out what it is
74909        if (config._dayOfYear != null) {
74910            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
74911
74912            if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
74913                getParsingFlags(config)._overflowDayOfYear = true;
74914            }
74915
74916            date = createUTCDate(yearToUse, 0, config._dayOfYear);
74917            config._a[MONTH] = date.getUTCMonth();
74918            config._a[DATE] = date.getUTCDate();
74919        }
74920
74921        // Default to current date.
74922        // * if no year, month, day of month are given, default to today
74923        // * if day of month is given, default month and year
74924        // * if month is given, default only year
74925        // * if year is given, don't default anything
74926        for (i = 0; i < 3 && config._a[i] == null; ++i) {
74927            config._a[i] = input[i] = currentDate[i];
74928        }
74929
74930        // Zero out whatever was not defaulted, including time
74931        for (; i < 7; i++) {
74932            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
74933        }
74934
74935        // Check for 24:00:00.000
74936        if (config._a[HOUR] === 24 &&
74937                config._a[MINUTE] === 0 &&
74938                config._a[SECOND] === 0 &&
74939                config._a[MILLISECOND] === 0) {
74940            config._nextDay = true;
74941            config._a[HOUR] = 0;
74942        }
74943
74944        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
74945        expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
74946
74947        // Apply timezone offset from input. The actual utcOffset can be changed
74948        // with parseZone.
74949        if (config._tzm != null) {
74950            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
74951        }
74952
74953        if (config._nextDay) {
74954            config._a[HOUR] = 24;
74955        }
74956
74957        // check for mismatching day of week
74958        if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
74959            getParsingFlags(config).weekdayMismatch = true;
74960        }
74961    }
74962
74963    function dayOfYearFromWeekInfo(config) {
74964        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
74965
74966        w = config._w;
74967        if (w.GG != null || w.W != null || w.E != null) {
74968            dow = 1;
74969            doy = 4;
74970
74971            // TODO: We need to take the current isoWeekYear, but that depends on
74972            // how we interpret now (local, utc, fixed offset). So create
74973            // a now version of current config (take local/utc/offset flags, and
74974            // create now).
74975            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
74976            week = defaults(w.W, 1);
74977            weekday = defaults(w.E, 1);
74978            if (weekday < 1 || weekday > 7) {
74979                weekdayOverflow = true;
74980            }
74981        } else {
74982            dow = config._locale._week.dow;
74983            doy = config._locale._week.doy;
74984
74985            var curWeek = weekOfYear(createLocal(), dow, doy);
74986
74987            weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
74988
74989            // Default to current week.
74990            week = defaults(w.w, curWeek.week);
74991
74992            if (w.d != null) {
74993                // weekday -- low day numbers are considered next week
74994                weekday = w.d;
74995                if (weekday < 0 || weekday > 6) {
74996                    weekdayOverflow = true;
74997                }
74998            } else if (w.e != null) {
74999                // local weekday -- counting starts from beginning of week
75000                weekday = w.e + dow;
75001                if (w.e < 0 || w.e > 6) {
75002                    weekdayOverflow = true;
75003                }
75004            } else {
75005                // default to beginning of week
75006                weekday = dow;
75007            }
75008        }
75009        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
75010            getParsingFlags(config)._overflowWeeks = true;
75011        } else if (weekdayOverflow != null) {
75012            getParsingFlags(config)._overflowWeekday = true;
75013        } else {
75014            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
75015            config._a[YEAR] = temp.year;
75016            config._dayOfYear = temp.dayOfYear;
75017        }
75018    }
75019
75020    // iso 8601 regex
75021    // 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)
75022    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)?)?$/;
75023    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)?)?$/;
75024
75025    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
75026
75027    var isoDates = [
75028        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
75029        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
75030        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
75031        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
75032        ['YYYY-DDD', /\d{4}-\d{3}/],
75033        ['YYYY-MM', /\d{4}-\d\d/, false],
75034        ['YYYYYYMMDD', /[+-]\d{10}/],
75035        ['YYYYMMDD', /\d{8}/],
75036        // YYYYMM is NOT allowed by the standard
75037        ['GGGG[W]WWE', /\d{4}W\d{3}/],
75038        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
75039        ['YYYYDDD', /\d{7}/]
75040    ];
75041
75042    // iso time formats and regexes
75043    var isoTimes = [
75044        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
75045        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
75046        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
75047        ['HH:mm', /\d\d:\d\d/],
75048        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
75049        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
75050        ['HHmmss', /\d\d\d\d\d\d/],
75051        ['HHmm', /\d\d\d\d/],
75052        ['HH', /\d\d/]
75053    ];
75054
75055    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
75056
75057    // date from iso format
75058    function configFromISO(config) {
75059        var i, l,
75060            string = config._i,
75061            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
75062            allowTime, dateFormat, timeFormat, tzFormat;
75063
75064        if (match) {
75065            getParsingFlags(config).iso = true;
75066
75067            for (i = 0, l = isoDates.length; i < l; i++) {
75068                if (isoDates[i][1].exec(match[1])) {
75069                    dateFormat = isoDates[i][0];
75070                    allowTime = isoDates[i][2] !== false;
75071                    break;
75072                }
75073            }
75074            if (dateFormat == null) {
75075                config._isValid = false;
75076                return;
75077            }
75078            if (match[3]) {
75079                for (i = 0, l = isoTimes.length; i < l; i++) {
75080                    if (isoTimes[i][1].exec(match[3])) {
75081                        // match[2] should be 'T' or space
75082                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
75083                        break;
75084                    }
75085                }
75086                if (timeFormat == null) {
75087                    config._isValid = false;
75088                    return;
75089                }
75090            }
75091            if (!allowTime && timeFormat != null) {
75092                config._isValid = false;
75093                return;
75094            }
75095            if (match[4]) {
75096                if (tzRegex.exec(match[4])) {
75097                    tzFormat = 'Z';
75098                } else {
75099                    config._isValid = false;
75100                    return;
75101                }
75102            }
75103            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
75104            configFromStringAndFormat(config);
75105        } else {
75106            config._isValid = false;
75107        }
75108    }
75109
75110    // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
75111    var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
75112
75113    function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
75114        var result = [
75115            untruncateYear(yearStr),
75116            defaultLocaleMonthsShort.indexOf(monthStr),
75117            parseInt(dayStr, 10),
75118            parseInt(hourStr, 10),
75119            parseInt(minuteStr, 10)
75120        ];
75121
75122        if (secondStr) {
75123            result.push(parseInt(secondStr, 10));
75124        }
75125
75126        return result;
75127    }
75128
75129    function untruncateYear(yearStr) {
75130        var year = parseInt(yearStr, 10);
75131        if (year <= 49) {
75132            return 2000 + year;
75133        } else if (year <= 999) {
75134            return 1900 + year;
75135        }
75136        return year;
75137    }
75138
75139    function preprocessRFC2822(s) {
75140        // Remove comments and folding whitespace and replace multiple-spaces with a single space
75141        return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
75142    }
75143
75144    function checkWeekday(weekdayStr, parsedInput, config) {
75145        if (weekdayStr) {
75146            // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
75147            var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
75148                weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
75149            if (weekdayProvided !== weekdayActual) {
75150                getParsingFlags(config).weekdayMismatch = true;
75151                config._isValid = false;
75152                return false;
75153            }
75154        }
75155        return true;
75156    }
75157
75158    var obsOffsets = {
75159        UT: 0,
75160        GMT: 0,
75161        EDT: -4 * 60,
75162        EST: -5 * 60,
75163        CDT: -5 * 60,
75164        CST: -6 * 60,
75165        MDT: -6 * 60,
75166        MST: -7 * 60,
75167        PDT: -7 * 60,
75168        PST: -8 * 60
75169    };
75170
75171    function calculateOffset(obsOffset, militaryOffset, numOffset) {
75172        if (obsOffset) {
75173            return obsOffsets[obsOffset];
75174        } else if (militaryOffset) {
75175            // the only allowed military tz is Z
75176            return 0;
75177        } else {
75178            var hm = parseInt(numOffset, 10);
75179            var m = hm % 100, h = (hm - m) / 100;
75180            return h * 60 + m;
75181        }
75182    }
75183
75184    // date and time from ref 2822 format
75185    function configFromRFC2822(config) {
75186        var match = rfc2822.exec(preprocessRFC2822(config._i));
75187        if (match) {
75188            var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
75189            if (!checkWeekday(match[1], parsedArray, config)) {
75190                return;
75191            }
75192
75193            config._a = parsedArray;
75194            config._tzm = calculateOffset(match[8], match[9], match[10]);
75195
75196            config._d = createUTCDate.apply(null, config._a);
75197            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
75198
75199            getParsingFlags(config).rfc2822 = true;
75200        } else {
75201            config._isValid = false;
75202        }
75203    }
75204
75205    // date from iso format or fallback
75206    function configFromString(config) {
75207        var matched = aspNetJsonRegex.exec(config._i);
75208
75209        if (matched !== null) {
75210            config._d = new Date(+matched[1]);
75211            return;
75212        }
75213
75214        configFromISO(config);
75215        if (config._isValid === false) {
75216            delete config._isValid;
75217        } else {
75218            return;
75219        }
75220
75221        configFromRFC2822(config);
75222        if (config._isValid === false) {
75223            delete config._isValid;
75224        } else {
75225            return;
75226        }
75227
75228        // Final attempt, use Input Fallback
75229        hooks.createFromInputFallback(config);
75230    }
75231
75232    hooks.createFromInputFallback = deprecate(
75233        'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
75234        'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
75235        'discouraged and will be removed in an upcoming major release. Please refer to ' +
75236        'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
75237        function (config) {
75238            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
75239        }
75240    );
75241
75242    // constant that refers to the ISO standard
75243    hooks.ISO_8601 = function () {};
75244
75245    // constant that refers to the RFC 2822 form
75246    hooks.RFC_2822 = function () {};
75247
75248    // date from string and format string
75249    function configFromStringAndFormat(config) {
75250        // TODO: Move this to another part of the creation flow to prevent circular deps
75251        if (config._f === hooks.ISO_8601) {
75252            configFromISO(config);
75253            return;
75254        }
75255        if (config._f === hooks.RFC_2822) {
75256            configFromRFC2822(config);
75257            return;
75258        }
75259        config._a = [];
75260        getParsingFlags(config).empty = true;
75261
75262        // This array is used to make a Date, either with `new Date` or `Date.UTC`
75263        var string = '' + config._i,
75264            i, parsedInput, tokens, token, skipped,
75265            stringLength = string.length,
75266            totalParsedInputLength = 0;
75267
75268        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
75269
75270        for (i = 0; i < tokens.length; i++) {
75271            token = tokens[i];
75272            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
75273            // console.log('token', token, 'parsedInput', parsedInput,
75274            //         'regex', getParseRegexForToken(token, config));
75275            if (parsedInput) {
75276                skipped = string.substr(0, string.indexOf(parsedInput));
75277                if (skipped.length > 0) {
75278                    getParsingFlags(config).unusedInput.push(skipped);
75279                }
75280                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
75281                totalParsedInputLength += parsedInput.length;
75282            }
75283            // don't parse if it's not a known token
75284            if (formatTokenFunctions[token]) {
75285                if (parsedInput) {
75286                    getParsingFlags(config).empty = false;
75287                }
75288                else {
75289                    getParsingFlags(config).unusedTokens.push(token);
75290                }
75291                addTimeToArrayFromToken(token, parsedInput, config);
75292            }
75293            else if (config._strict && !parsedInput) {
75294                getParsingFlags(config).unusedTokens.push(token);
75295            }
75296        }
75297
75298        // add remaining unparsed input length to the string
75299        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
75300        if (string.length > 0) {
75301            getParsingFlags(config).unusedInput.push(string);
75302        }
75303
75304        // clear _12h flag if hour is <= 12
75305        if (config._a[HOUR] <= 12 &&
75306            getParsingFlags(config).bigHour === true &&
75307            config._a[HOUR] > 0) {
75308            getParsingFlags(config).bigHour = undefined;
75309        }
75310
75311        getParsingFlags(config).parsedDateParts = config._a.slice(0);
75312        getParsingFlags(config).meridiem = config._meridiem;
75313        // handle meridiem
75314        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
75315
75316        configFromArray(config);
75317        checkOverflow(config);
75318    }
75319
75320
75321    function meridiemFixWrap (locale, hour, meridiem) {
75322        var isPm;
75323
75324        if (meridiem == null) {
75325            // nothing to do
75326            return hour;
75327        }
75328        if (locale.meridiemHour != null) {
75329            return locale.meridiemHour(hour, meridiem);
75330        } else if (locale.isPM != null) {
75331            // Fallback
75332            isPm = locale.isPM(meridiem);
75333            if (isPm && hour < 12) {
75334                hour += 12;
75335            }
75336            if (!isPm && hour === 12) {
75337                hour = 0;
75338            }
75339            return hour;
75340        } else {
75341            // this is not supposed to happen
75342            return hour;
75343        }
75344    }
75345
75346    // date from string and array of format strings
75347    function configFromStringAndArray(config) {
75348        var tempConfig,
75349            bestMoment,
75350
75351            scoreToBeat,
75352            i,
75353            currentScore;
75354
75355        if (config._f.length === 0) {
75356            getParsingFlags(config).invalidFormat = true;
75357            config._d = new Date(NaN);
75358            return;
75359        }
75360
75361        for (i = 0; i < config._f.length; i++) {
75362            currentScore = 0;
75363            tempConfig = copyConfig({}, config);
75364            if (config._useUTC != null) {
75365                tempConfig._useUTC = config._useUTC;
75366            }
75367            tempConfig._f = config._f[i];
75368            configFromStringAndFormat(tempConfig);
75369
75370            if (!isValid(tempConfig)) {
75371                continue;
75372            }
75373
75374            // if there is any input that was not parsed add a penalty for that format
75375            currentScore += getParsingFlags(tempConfig).charsLeftOver;
75376
75377            //or tokens
75378            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
75379
75380            getParsingFlags(tempConfig).score = currentScore;
75381
75382            if (scoreToBeat == null || currentScore < scoreToBeat) {
75383                scoreToBeat = currentScore;
75384                bestMoment = tempConfig;
75385            }
75386        }
75387
75388        extend(config, bestMoment || tempConfig);
75389    }
75390
75391    function configFromObject(config) {
75392        if (config._d) {
75393            return;
75394        }
75395
75396        var i = normalizeObjectUnits(config._i);
75397        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
75398            return obj && parseInt(obj, 10);
75399        });
75400
75401        configFromArray(config);
75402    }
75403
75404    function createFromConfig (config) {
75405        var res = new Moment(checkOverflow(prepareConfig(config)));
75406        if (res._nextDay) {
75407            // Adding is smart enough around DST
75408            res.add(1, 'd');
75409            res._nextDay = undefined;
75410        }
75411
75412        return res;
75413    }
75414
75415    function prepareConfig (config) {
75416        var input = config._i,
75417            format = config._f;
75418
75419        config._locale = config._locale || getLocale(config._l);
75420
75421        if (input === null || (format === undefined && input === '')) {
75422            return createInvalid({nullInput: true});
75423        }
75424
75425        if (typeof input === 'string') {
75426            config._i = input = config._locale.preparse(input);
75427        }
75428
75429        if (isMoment(input)) {
75430            return new Moment(checkOverflow(input));
75431        } else if (isDate(input)) {
75432            config._d = input;
75433        } else if (isArray(format)) {
75434            configFromStringAndArray(config);
75435        } else if (format) {
75436            configFromStringAndFormat(config);
75437        }  else {
75438            configFromInput(config);
75439        }
75440
75441        if (!isValid(config)) {
75442            config._d = null;
75443        }
75444
75445        return config;
75446    }
75447
75448    function configFromInput(config) {
75449        var input = config._i;
75450        if (isUndefined(input)) {
75451            config._d = new Date(hooks.now());
75452        } else if (isDate(input)) {
75453            config._d = new Date(input.valueOf());
75454        } else if (typeof input === 'string') {
75455            configFromString(config);
75456        } else if (isArray(input)) {
75457            config._a = map(input.slice(0), function (obj) {
75458                return parseInt(obj, 10);
75459            });
75460            configFromArray(config);
75461        } else if (isObject(input)) {
75462            configFromObject(config);
75463        } else if (isNumber(input)) {
75464            // from milliseconds
75465            config._d = new Date(input);
75466        } else {
75467            hooks.createFromInputFallback(config);
75468        }
75469    }
75470
75471    function createLocalOrUTC (input, format, locale, strict, isUTC) {
75472        var c = {};
75473
75474        if (locale === true || locale === false) {
75475            strict = locale;
75476            locale = undefined;
75477        }
75478
75479        if ((isObject(input) && isObjectEmpty(input)) ||
75480                (isArray(input) && input.length === 0)) {
75481            input = undefined;
75482        }
75483        // object construction must be done this way.
75484        // https://github.com/moment/moment/issues/1423
75485        c._isAMomentObject = true;
75486        c._useUTC = c._isUTC = isUTC;
75487        c._l = locale;
75488        c._i = input;
75489        c._f = format;
75490        c._strict = strict;
75491
75492        return createFromConfig(c);
75493    }
75494
75495    function createLocal (input, format, locale, strict) {
75496        return createLocalOrUTC(input, format, locale, strict, false);
75497    }
75498
75499    var prototypeMin = deprecate(
75500        'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
75501        function () {
75502            var other = createLocal.apply(null, arguments);
75503            if (this.isValid() && other.isValid()) {
75504                return other < this ? this : other;
75505            } else {
75506                return createInvalid();
75507            }
75508        }
75509    );
75510
75511    var prototypeMax = deprecate(
75512        'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
75513        function () {
75514            var other = createLocal.apply(null, arguments);
75515            if (this.isValid() && other.isValid()) {
75516                return other > this ? this : other;
75517            } else {
75518                return createInvalid();
75519            }
75520        }
75521    );
75522
75523    // Pick a moment m from moments so that m[fn](other) is true for all
75524    // other. This relies on the function fn to be transitive.
75525    //
75526    // moments should either be an array of moment objects or an array, whose
75527    // first element is an array of moment objects.
75528    function pickBy(fn, moments) {
75529        var res, i;
75530        if (moments.length === 1 && isArray(moments[0])) {
75531            moments = moments[0];
75532        }
75533        if (!moments.length) {
75534            return createLocal();
75535        }
75536        res = moments[0];
75537        for (i = 1; i < moments.length; ++i) {
75538            if (!moments[i].isValid() || moments[i][fn](res)) {
75539                res = moments[i];
75540            }
75541        }
75542        return res;
75543    }
75544
75545    // TODO: Use [].sort instead?
75546    function min () {
75547        var args = [].slice.call(arguments, 0);
75548
75549        return pickBy('isBefore', args);
75550    }
75551
75552    function max () {
75553        var args = [].slice.call(arguments, 0);
75554
75555        return pickBy('isAfter', args);
75556    }
75557
75558    var now = function () {
75559        return Date.now ? Date.now() : +(new Date());
75560    };
75561
75562    var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
75563
75564    function isDurationValid(m) {
75565        for (var key in m) {
75566            if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
75567                return false;
75568            }
75569        }
75570
75571        var unitHasDecimal = false;
75572        for (var i = 0; i < ordering.length; ++i) {
75573            if (m[ordering[i]]) {
75574                if (unitHasDecimal) {
75575                    return false; // only allow non-integers for smallest unit
75576                }
75577                if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
75578                    unitHasDecimal = true;
75579                }
75580            }
75581        }
75582
75583        return true;
75584    }
75585
75586    function isValid$1() {
75587        return this._isValid;
75588    }
75589
75590    function createInvalid$1() {
75591        return createDuration(NaN);
75592    }
75593
75594    function Duration (duration) {
75595        var normalizedInput = normalizeObjectUnits(duration),
75596            years = normalizedInput.year || 0,
75597            quarters = normalizedInput.quarter || 0,
75598            months = normalizedInput.month || 0,
75599            weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
75600            days = normalizedInput.day || 0,
75601            hours = normalizedInput.hour || 0,
75602            minutes = normalizedInput.minute || 0,
75603            seconds = normalizedInput.second || 0,
75604            milliseconds = normalizedInput.millisecond || 0;
75605
75606        this._isValid = isDurationValid(normalizedInput);
75607
75608        // representation for dateAddRemove
75609        this._milliseconds = +milliseconds +
75610            seconds * 1e3 + // 1000
75611            minutes * 6e4 + // 1000 * 60
75612            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
75613        // Because of dateAddRemove treats 24 hours as different from a
75614        // day when working around DST, we need to store them separately
75615        this._days = +days +
75616            weeks * 7;
75617        // It is impossible to translate months into days without knowing
75618        // which months you are are talking about, so we have to store
75619        // it separately.
75620        this._months = +months +
75621            quarters * 3 +
75622            years * 12;
75623
75624        this._data = {};
75625
75626        this._locale = getLocale();
75627
75628        this._bubble();
75629    }
75630
75631    function isDuration (obj) {
75632        return obj instanceof Duration;
75633    }
75634
75635    function absRound (number) {
75636        if (number < 0) {
75637            return Math.round(-1 * number) * -1;
75638        } else {
75639            return Math.round(number);
75640        }
75641    }
75642
75643    // FORMATTING
75644
75645    function offset (token, separator) {
75646        addFormatToken(token, 0, 0, function () {
75647            var offset = this.utcOffset();
75648            var sign = '+';
75649            if (offset < 0) {
75650                offset = -offset;
75651                sign = '-';
75652            }
75653            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
75654        });
75655    }
75656
75657    offset('Z', ':');
75658    offset('ZZ', '');
75659
75660    // PARSING
75661
75662    addRegexToken('Z',  matchShortOffset);
75663    addRegexToken('ZZ', matchShortOffset);
75664    addParseToken(['Z', 'ZZ'], function (input, array, config) {
75665        config._useUTC = true;
75666        config._tzm = offsetFromString(matchShortOffset, input);
75667    });
75668
75669    // HELPERS
75670
75671    // timezone chunker
75672    // '+10:00' > ['10',  '00']
75673    // '-1530'  > ['-15', '30']
75674    var chunkOffset = /([\+\-]|\d\d)/gi;
75675
75676    function offsetFromString(matcher, string) {
75677        var matches = (string || '').match(matcher);
75678
75679        if (matches === null) {
75680            return null;
75681        }
75682
75683        var chunk   = matches[matches.length - 1] || [];
75684        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
75685        var minutes = +(parts[1] * 60) + toInt(parts[2]);
75686
75687        return minutes === 0 ?
75688          0 :
75689          parts[0] === '+' ? minutes : -minutes;
75690    }
75691
75692    // Return a moment from input, that is local/utc/zone equivalent to model.
75693    function cloneWithOffset(input, model) {
75694        var res, diff;
75695        if (model._isUTC) {
75696            res = model.clone();
75697            diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
75698            // Use low-level api, because this fn is low-level api.
75699            res._d.setTime(res._d.valueOf() + diff);
75700            hooks.updateOffset(res, false);
75701            return res;
75702        } else {
75703            return createLocal(input).local();
75704        }
75705    }
75706
75707    function getDateOffset (m) {
75708        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
75709        // https://github.com/moment/moment/pull/1871
75710        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
75711    }
75712
75713    // HOOKS
75714
75715    // This function will be called whenever a moment is mutated.
75716    // It is intended to keep the offset in sync with the timezone.
75717    hooks.updateOffset = function () {};
75718
75719    // MOMENTS
75720
75721    // keepLocalTime = true means only change the timezone, without
75722    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
75723    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
75724    // +0200, so we adjust the time as needed, to be valid.
75725    //
75726    // Keeping the time actually adds/subtracts (one hour)
75727    // from the actual represented time. That is why we call updateOffset
75728    // a second time. In case it wants us to change the offset again
75729    // _changeInProgress == true case, then we have to adjust, because
75730    // there is no such time in the given timezone.
75731    function getSetOffset (input, keepLocalTime, keepMinutes) {
75732        var offset = this._offset || 0,
75733            localAdjust;
75734        if (!this.isValid()) {
75735            return input != null ? this : NaN;
75736        }
75737        if (input != null) {
75738            if (typeof input === 'string') {
75739                input = offsetFromString(matchShortOffset, input);
75740                if (input === null) {
75741                    return this;
75742                }
75743            } else if (Math.abs(input) < 16 && !keepMinutes) {
75744                input = input * 60;
75745            }
75746            if (!this._isUTC && keepLocalTime) {
75747                localAdjust = getDateOffset(this);
75748            }
75749            this._offset = input;
75750            this._isUTC = true;
75751            if (localAdjust != null) {
75752                this.add(localAdjust, 'm');
75753            }
75754            if (offset !== input) {
75755                if (!keepLocalTime || this._changeInProgress) {
75756                    addSubtract(this, createDuration(input - offset, 'm'), 1, false);
75757                } else if (!this._changeInProgress) {
75758                    this._changeInProgress = true;
75759                    hooks.updateOffset(this, true);
75760                    this._changeInProgress = null;
75761                }
75762            }
75763            return this;
75764        } else {
75765            return this._isUTC ? offset : getDateOffset(this);
75766        }
75767    }
75768
75769    function getSetZone (input, keepLocalTime) {
75770        if (input != null) {
75771            if (typeof input !== 'string') {
75772                input = -input;
75773            }
75774
75775            this.utcOffset(input, keepLocalTime);
75776
75777            return this;
75778        } else {
75779            return -this.utcOffset();
75780        }
75781    }
75782
75783    function setOffsetToUTC (keepLocalTime) {
75784        return this.utcOffset(0, keepLocalTime);
75785    }
75786
75787    function setOffsetToLocal (keepLocalTime) {
75788        if (this._isUTC) {
75789            this.utcOffset(0, keepLocalTime);
75790            this._isUTC = false;
75791
75792            if (keepLocalTime) {
75793                this.subtract(getDateOffset(this), 'm');
75794            }
75795        }
75796        return this;
75797    }
75798
75799    function setOffsetToParsedOffset () {
75800        if (this._tzm != null) {
75801            this.utcOffset(this._tzm, false, true);
75802        } else if (typeof this._i === 'string') {
75803            var tZone = offsetFromString(matchOffset, this._i);
75804            if (tZone != null) {
75805                this.utcOffset(tZone);
75806            }
75807            else {
75808                this.utcOffset(0, true);
75809            }
75810        }
75811        return this;
75812    }
75813
75814    function hasAlignedHourOffset (input) {
75815        if (!this.isValid()) {
75816            return false;
75817        }
75818        input = input ? createLocal(input).utcOffset() : 0;
75819
75820        return (this.utcOffset() - input) % 60 === 0;
75821    }
75822
75823    function isDaylightSavingTime () {
75824        return (
75825            this.utcOffset() > this.clone().month(0).utcOffset() ||
75826            this.utcOffset() > this.clone().month(5).utcOffset()
75827        );
75828    }
75829
75830    function isDaylightSavingTimeShifted () {
75831        if (!isUndefined(this._isDSTShifted)) {
75832            return this._isDSTShifted;
75833        }
75834
75835        var c = {};
75836
75837        copyConfig(c, this);
75838        c = prepareConfig(c);
75839
75840        if (c._a) {
75841            var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
75842            this._isDSTShifted = this.isValid() &&
75843                compareArrays(c._a, other.toArray()) > 0;
75844        } else {
75845            this._isDSTShifted = false;
75846        }
75847
75848        return this._isDSTShifted;
75849    }
75850
75851    function isLocal () {
75852        return this.isValid() ? !this._isUTC : false;
75853    }
75854
75855    function isUtcOffset () {
75856        return this.isValid() ? this._isUTC : false;
75857    }
75858
75859    function isUtc () {
75860        return this.isValid() ? this._isUTC && this._offset === 0 : false;
75861    }
75862
75863    // ASP.NET json date format regex
75864    var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
75865
75866    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
75867    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
75868    // and further modified to allow for strings containing both week and day
75869    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)?)?$/;
75870
75871    function createDuration (input, key) {
75872        var duration = input,
75873            // matching against regexp is expensive, do it on demand
75874            match = null,
75875            sign,
75876            ret,
75877            diffRes;
75878
75879        if (isDuration(input)) {
75880            duration = {
75881                ms : input._milliseconds,
75882                d  : input._days,
75883                M  : input._months
75884            };
75885        } else if (isNumber(input)) {
75886            duration = {};
75887            if (key) {
75888                duration[key] = input;
75889            } else {
75890                duration.milliseconds = input;
75891            }
75892        } else if (!!(match = aspNetRegex.exec(input))) {
75893            sign = (match[1] === '-') ? -1 : 1;
75894            duration = {
75895                y  : 0,
75896                d  : toInt(match[DATE])                         * sign,
75897                h  : toInt(match[HOUR])                         * sign,
75898                m  : toInt(match[MINUTE])                       * sign,
75899                s  : toInt(match[SECOND])                       * sign,
75900                ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
75901            };
75902        } else if (!!(match = isoRegex.exec(input))) {
75903            sign = (match[1] === '-') ? -1 : 1;
75904            duration = {
75905                y : parseIso(match[2], sign),
75906                M : parseIso(match[3], sign),
75907                w : parseIso(match[4], sign),
75908                d : parseIso(match[5], sign),
75909                h : parseIso(match[6], sign),
75910                m : parseIso(match[7], sign),
75911                s : parseIso(match[8], sign)
75912            };
75913        } else if (duration == null) {// checks for null or undefined
75914            duration = {};
75915        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
75916            diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
75917
75918            duration = {};
75919            duration.ms = diffRes.milliseconds;
75920            duration.M = diffRes.months;
75921        }
75922
75923        ret = new Duration(duration);
75924
75925        if (isDuration(input) && hasOwnProp(input, '_locale')) {
75926            ret._locale = input._locale;
75927        }
75928
75929        return ret;
75930    }
75931
75932    createDuration.fn = Duration.prototype;
75933    createDuration.invalid = createInvalid$1;
75934
75935    function parseIso (inp, sign) {
75936        // We'd normally use ~~inp for this, but unfortunately it also
75937        // converts floats to ints.
75938        // inp may be undefined, so careful calling replace on it.
75939        var res = inp && parseFloat(inp.replace(',', '.'));
75940        // apply sign while we're at it
75941        return (isNaN(res) ? 0 : res) * sign;
75942    }
75943
75944    function positiveMomentsDifference(base, other) {
75945        var res = {};
75946
75947        res.months = other.month() - base.month() +
75948            (other.year() - base.year()) * 12;
75949        if (base.clone().add(res.months, 'M').isAfter(other)) {
75950            --res.months;
75951        }
75952
75953        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
75954
75955        return res;
75956    }
75957
75958    function momentsDifference(base, other) {
75959        var res;
75960        if (!(base.isValid() && other.isValid())) {
75961            return {milliseconds: 0, months: 0};
75962        }
75963
75964        other = cloneWithOffset(other, base);
75965        if (base.isBefore(other)) {
75966            res = positiveMomentsDifference(base, other);
75967        } else {
75968            res = positiveMomentsDifference(other, base);
75969            res.milliseconds = -res.milliseconds;
75970            res.months = -res.months;
75971        }
75972
75973        return res;
75974    }
75975
75976    // TODO: remove 'name' arg after deprecation is removed
75977    function createAdder(direction, name) {
75978        return function (val, period) {
75979            var dur, tmp;
75980            //invert the arguments, but complain about it
75981            if (period !== null && !isNaN(+period)) {
75982                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
75983                'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
75984                tmp = val; val = period; period = tmp;
75985            }
75986
75987            val = typeof val === 'string' ? +val : val;
75988            dur = createDuration(val, period);
75989            addSubtract(this, dur, direction);
75990            return this;
75991        };
75992    }
75993
75994    function addSubtract (mom, duration, isAdding, updateOffset) {
75995        var milliseconds = duration._milliseconds,
75996            days = absRound(duration._days),
75997            months = absRound(duration._months);
75998
75999        if (!mom.isValid()) {
76000            // No op
76001            return;
76002        }
76003
76004        updateOffset = updateOffset == null ? true : updateOffset;
76005
76006        if (months) {
76007            setMonth(mom, get(mom, 'Month') + months * isAdding);
76008        }
76009        if (days) {
76010            set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
76011        }
76012        if (milliseconds) {
76013            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
76014        }
76015        if (updateOffset) {
76016            hooks.updateOffset(mom, days || months);
76017        }
76018    }
76019
76020    var add      = createAdder(1, 'add');
76021    var subtract = createAdder(-1, 'subtract');
76022
76023    function getCalendarFormat(myMoment, now) {
76024        var diff = myMoment.diff(now, 'days', true);
76025        return diff < -6 ? 'sameElse' :
76026                diff < -1 ? 'lastWeek' :
76027                diff < 0 ? 'lastDay' :
76028                diff < 1 ? 'sameDay' :
76029                diff < 2 ? 'nextDay' :
76030                diff < 7 ? 'nextWeek' : 'sameElse';
76031    }
76032
76033    function calendar$1 (time, formats) {
76034        // We want to compare the start of today, vs this.
76035        // Getting start-of-today depends on whether we're local/utc/offset or not.
76036        var now = time || createLocal(),
76037            sod = cloneWithOffset(now, this).startOf('day'),
76038            format = hooks.calendarFormat(this, sod) || 'sameElse';
76039
76040        var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
76041
76042        return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
76043    }
76044
76045    function clone () {
76046        return new Moment(this);
76047    }
76048
76049    function isAfter (input, units) {
76050        var localInput = isMoment(input) ? input : createLocal(input);
76051        if (!(this.isValid() && localInput.isValid())) {
76052            return false;
76053        }
76054        units = normalizeUnits(units) || 'millisecond';
76055        if (units === 'millisecond') {
76056            return this.valueOf() > localInput.valueOf();
76057        } else {
76058            return localInput.valueOf() < this.clone().startOf(units).valueOf();
76059        }
76060    }
76061
76062    function isBefore (input, units) {
76063        var localInput = isMoment(input) ? input : createLocal(input);
76064        if (!(this.isValid() && localInput.isValid())) {
76065            return false;
76066        }
76067        units = normalizeUnits(units) || 'millisecond';
76068        if (units === 'millisecond') {
76069            return this.valueOf() < localInput.valueOf();
76070        } else {
76071            return this.clone().endOf(units).valueOf() < localInput.valueOf();
76072        }
76073    }
76074
76075    function isBetween (from, to, units, inclusivity) {
76076        var localFrom = isMoment(from) ? from : createLocal(from),
76077            localTo = isMoment(to) ? to : createLocal(to);
76078        if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
76079            return false;
76080        }
76081        inclusivity = inclusivity || '()';
76082        return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) &&
76083            (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
76084    }
76085
76086    function isSame (input, units) {
76087        var localInput = isMoment(input) ? input : createLocal(input),
76088            inputMs;
76089        if (!(this.isValid() && localInput.isValid())) {
76090            return false;
76091        }
76092        units = normalizeUnits(units) || 'millisecond';
76093        if (units === 'millisecond') {
76094            return this.valueOf() === localInput.valueOf();
76095        } else {
76096            inputMs = localInput.valueOf();
76097            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
76098        }
76099    }
76100
76101    function isSameOrAfter (input, units) {
76102        return this.isSame(input, units) || this.isAfter(input, units);
76103    }
76104
76105    function isSameOrBefore (input, units) {
76106        return this.isSame(input, units) || this.isBefore(input, units);
76107    }
76108
76109    function diff (input, units, asFloat) {
76110        var that,
76111            zoneDelta,
76112            output;
76113
76114        if (!this.isValid()) {
76115            return NaN;
76116        }
76117
76118        that = cloneWithOffset(input, this);
76119
76120        if (!that.isValid()) {
76121            return NaN;
76122        }
76123
76124        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
76125
76126        units = normalizeUnits(units);
76127
76128        switch (units) {
76129            case 'year': output = monthDiff(this, that) / 12; break;
76130            case 'month': output = monthDiff(this, that); break;
76131            case 'quarter': output = monthDiff(this, that) / 3; break;
76132            case 'second': output = (this - that) / 1e3; break; // 1000
76133            case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
76134            case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
76135            case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
76136            case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
76137            default: output = this - that;
76138        }
76139
76140        return asFloat ? output : absFloor(output);
76141    }
76142
76143    function monthDiff (a, b) {
76144        // difference in months
76145        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
76146            // b is in (anchor - 1 month, anchor + 1 month)
76147            anchor = a.clone().add(wholeMonthDiff, 'months'),
76148            anchor2, adjust;
76149
76150        if (b - anchor < 0) {
76151            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
76152            // linear across the month
76153            adjust = (b - anchor) / (anchor - anchor2);
76154        } else {
76155            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
76156            // linear across the month
76157            adjust = (b - anchor) / (anchor2 - anchor);
76158        }
76159
76160        //check for negative zero, return zero if negative zero
76161        return -(wholeMonthDiff + adjust) || 0;
76162    }
76163
76164    hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
76165    hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
76166
76167    function toString () {
76168        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
76169    }
76170
76171    function toISOString(keepOffset) {
76172        if (!this.isValid()) {
76173            return null;
76174        }
76175        var utc = keepOffset !== true;
76176        var m = utc ? this.clone().utc() : this;
76177        if (m.year() < 0 || m.year() > 9999) {
76178            return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
76179        }
76180        if (isFunction(Date.prototype.toISOString)) {
76181            // native implementation is ~50x faster, use it when we can
76182            if (utc) {
76183                return this.toDate().toISOString();
76184            } else {
76185                return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
76186            }
76187        }
76188        return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
76189    }
76190
76191    /**
76192     * Return a human readable representation of a moment that can
76193     * also be evaluated to get a new moment which is the same
76194     *
76195     * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
76196     */
76197    function inspect () {
76198        if (!this.isValid()) {
76199            return 'moment.invalid(/* ' + this._i + ' */)';
76200        }
76201        var func = 'moment';
76202        var zone = '';
76203        if (!this.isLocal()) {
76204            func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
76205            zone = 'Z';
76206        }
76207        var prefix = '[' + func + '("]';
76208        var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
76209        var datetime = '-MM-DD[T]HH:mm:ss.SSS';
76210        var suffix = zone + '[")]';
76211
76212        return this.format(prefix + year + datetime + suffix);
76213    }
76214
76215    function format (inputString) {
76216        if (!inputString) {
76217            inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
76218        }
76219        var output = formatMoment(this, inputString);
76220        return this.localeData().postformat(output);
76221    }
76222
76223    function from (time, withoutSuffix) {
76224        if (this.isValid() &&
76225                ((isMoment(time) && time.isValid()) ||
76226                 createLocal(time).isValid())) {
76227            return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
76228        } else {
76229            return this.localeData().invalidDate();
76230        }
76231    }
76232
76233    function fromNow (withoutSuffix) {
76234        return this.from(createLocal(), withoutSuffix);
76235    }
76236
76237    function to (time, withoutSuffix) {
76238        if (this.isValid() &&
76239                ((isMoment(time) && time.isValid()) ||
76240                 createLocal(time).isValid())) {
76241            return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
76242        } else {
76243            return this.localeData().invalidDate();
76244        }
76245    }
76246
76247    function toNow (withoutSuffix) {
76248        return this.to(createLocal(), withoutSuffix);
76249    }
76250
76251    // If passed a locale key, it will set the locale for this
76252    // instance.  Otherwise, it will return the locale configuration
76253    // variables for this instance.
76254    function locale (key) {
76255        var newLocaleData;
76256
76257        if (key === undefined) {
76258            return this._locale._abbr;
76259        } else {
76260            newLocaleData = getLocale(key);
76261            if (newLocaleData != null) {
76262                this._locale = newLocaleData;
76263            }
76264            return this;
76265        }
76266    }
76267
76268    var lang = deprecate(
76269        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
76270        function (key) {
76271            if (key === undefined) {
76272                return this.localeData();
76273            } else {
76274                return this.locale(key);
76275            }
76276        }
76277    );
76278
76279    function localeData () {
76280        return this._locale;
76281    }
76282
76283    var MS_PER_SECOND = 1000;
76284    var MS_PER_MINUTE = 60 * MS_PER_SECOND;
76285    var MS_PER_HOUR = 60 * MS_PER_MINUTE;
76286    var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
76287
76288    // actual modulo - handles negative numbers (for dates before 1970):
76289    function mod$1(dividend, divisor) {
76290        return (dividend % divisor + divisor) % divisor;
76291    }
76292
76293    function localStartOfDate(y, m, d) {
76294        // the date constructor remaps years 0-99 to 1900-1999
76295        if (y < 100 && y >= 0) {
76296            // preserve leap years using a full 400 year cycle, then reset
76297            return new Date(y + 400, m, d) - MS_PER_400_YEARS;
76298        } else {
76299            return new Date(y, m, d).valueOf();
76300        }
76301    }
76302
76303    function utcStartOfDate(y, m, d) {
76304        // Date.UTC remaps years 0-99 to 1900-1999
76305        if (y < 100 && y >= 0) {
76306            // preserve leap years using a full 400 year cycle, then reset
76307            return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
76308        } else {
76309            return Date.UTC(y, m, d);
76310        }
76311    }
76312
76313    function startOf (units) {
76314        var time;
76315        units = normalizeUnits(units);
76316        if (units === undefined || units === 'millisecond' || !this.isValid()) {
76317            return this;
76318        }
76319
76320        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
76321
76322        switch (units) {
76323            case 'year':
76324                time = startOfDate(this.year(), 0, 1);
76325                break;
76326            case 'quarter':
76327                time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
76328                break;
76329            case 'month':
76330                time = startOfDate(this.year(), this.month(), 1);
76331                break;
76332            case 'week':
76333                time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
76334                break;
76335            case 'isoWeek':
76336                time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
76337                break;
76338            case 'day':
76339            case 'date':
76340                time = startOfDate(this.year(), this.month(), this.date());
76341                break;
76342            case 'hour':
76343                time = this._d.valueOf();
76344                time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
76345                break;
76346            case 'minute':
76347                time = this._d.valueOf();
76348                time -= mod$1(time, MS_PER_MINUTE);
76349                break;
76350            case 'second':
76351                time = this._d.valueOf();
76352                time -= mod$1(time, MS_PER_SECOND);
76353                break;
76354        }
76355
76356        this._d.setTime(time);
76357        hooks.updateOffset(this, true);
76358        return this;
76359    }
76360
76361    function endOf (units) {
76362        var time;
76363        units = normalizeUnits(units);
76364        if (units === undefined || units === 'millisecond' || !this.isValid()) {
76365            return this;
76366        }
76367
76368        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
76369
76370        switch (units) {
76371            case 'year':
76372                time = startOfDate(this.year() + 1, 0, 1) - 1;
76373                break;
76374            case 'quarter':
76375                time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
76376                break;
76377            case 'month':
76378                time = startOfDate(this.year(), this.month() + 1, 1) - 1;
76379                break;
76380            case 'week':
76381                time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
76382                break;
76383            case 'isoWeek':
76384                time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
76385                break;
76386            case 'day':
76387            case 'date':
76388                time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
76389                break;
76390            case 'hour':
76391                time = this._d.valueOf();
76392                time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
76393                break;
76394            case 'minute':
76395                time = this._d.valueOf();
76396                time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
76397                break;
76398            case 'second':
76399                time = this._d.valueOf();
76400                time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
76401                break;
76402        }
76403
76404        this._d.setTime(time);
76405        hooks.updateOffset(this, true);
76406        return this;
76407    }
76408
76409    function valueOf () {
76410        return this._d.valueOf() - ((this._offset || 0) * 60000);
76411    }
76412
76413    function unix () {
76414        return Math.floor(this.valueOf() / 1000);
76415    }
76416
76417    function toDate () {
76418        return new Date(this.valueOf());
76419    }
76420
76421    function toArray () {
76422        var m = this;
76423        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
76424    }
76425
76426    function toObject () {
76427        var m = this;
76428        return {
76429            years: m.year(),
76430            months: m.month(),
76431            date: m.date(),
76432            hours: m.hours(),
76433            minutes: m.minutes(),
76434            seconds: m.seconds(),
76435            milliseconds: m.milliseconds()
76436        };
76437    }
76438
76439    function toJSON () {
76440        // new Date(NaN).toJSON() === null
76441        return this.isValid() ? this.toISOString() : null;
76442    }
76443
76444    function isValid$2 () {
76445        return isValid(this);
76446    }
76447
76448    function parsingFlags () {
76449        return extend({}, getParsingFlags(this));
76450    }
76451
76452    function invalidAt () {
76453        return getParsingFlags(this).overflow;
76454    }
76455
76456    function creationData() {
76457        return {
76458            input: this._i,
76459            format: this._f,
76460            locale: this._locale,
76461            isUTC: this._isUTC,
76462            strict: this._strict
76463        };
76464    }
76465
76466    // FORMATTING
76467
76468    addFormatToken(0, ['gg', 2], 0, function () {
76469        return this.weekYear() % 100;
76470    });
76471
76472    addFormatToken(0, ['GG', 2], 0, function () {
76473        return this.isoWeekYear() % 100;
76474    });
76475
76476    function addWeekYearFormatToken (token, getter) {
76477        addFormatToken(0, [token, token.length], 0, getter);
76478    }
76479
76480    addWeekYearFormatToken('gggg',     'weekYear');
76481    addWeekYearFormatToken('ggggg',    'weekYear');
76482    addWeekYearFormatToken('GGGG',  'isoWeekYear');
76483    addWeekYearFormatToken('GGGGG', 'isoWeekYear');
76484
76485    // ALIASES
76486
76487    addUnitAlias('weekYear', 'gg');
76488    addUnitAlias('isoWeekYear', 'GG');
76489
76490    // PRIORITY
76491
76492    addUnitPriority('weekYear', 1);
76493    addUnitPriority('isoWeekYear', 1);
76494
76495
76496    // PARSING
76497
76498    addRegexToken('G',      matchSigned);
76499    addRegexToken('g',      matchSigned);
76500    addRegexToken('GG',     match1to2, match2);
76501    addRegexToken('gg',     match1to2, match2);
76502    addRegexToken('GGGG',   match1to4, match4);
76503    addRegexToken('gggg',   match1to4, match4);
76504    addRegexToken('GGGGG',  match1to6, match6);
76505    addRegexToken('ggggg',  match1to6, match6);
76506
76507    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
76508        week[token.substr(0, 2)] = toInt(input);
76509    });
76510
76511    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
76512        week[token] = hooks.parseTwoDigitYear(input);
76513    });
76514
76515    // MOMENTS
76516
76517    function getSetWeekYear (input) {
76518        return getSetWeekYearHelper.call(this,
76519                input,
76520                this.week(),
76521                this.weekday(),
76522                this.localeData()._week.dow,
76523                this.localeData()._week.doy);
76524    }
76525
76526    function getSetISOWeekYear (input) {
76527        return getSetWeekYearHelper.call(this,
76528                input, this.isoWeek(), this.isoWeekday(), 1, 4);
76529    }
76530
76531    function getISOWeeksInYear () {
76532        return weeksInYear(this.year(), 1, 4);
76533    }
76534
76535    function getWeeksInYear () {
76536        var weekInfo = this.localeData()._week;
76537        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
76538    }
76539
76540    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
76541        var weeksTarget;
76542        if (input == null) {
76543            return weekOfYear(this, dow, doy).year;
76544        } else {
76545            weeksTarget = weeksInYear(input, dow, doy);
76546            if (week > weeksTarget) {
76547                week = weeksTarget;
76548            }
76549            return setWeekAll.call(this, input, week, weekday, dow, doy);
76550        }
76551    }
76552
76553    function setWeekAll(weekYear, week, weekday, dow, doy) {
76554        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
76555            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
76556
76557        this.year(date.getUTCFullYear());
76558        this.month(date.getUTCMonth());
76559        this.date(date.getUTCDate());
76560        return this;
76561    }
76562
76563    // FORMATTING
76564
76565    addFormatToken('Q', 0, 'Qo', 'quarter');
76566
76567    // ALIASES
76568
76569    addUnitAlias('quarter', 'Q');
76570
76571    // PRIORITY
76572
76573    addUnitPriority('quarter', 7);
76574
76575    // PARSING
76576
76577    addRegexToken('Q', match1);
76578    addParseToken('Q', function (input, array) {
76579        array[MONTH] = (toInt(input) - 1) * 3;
76580    });
76581
76582    // MOMENTS
76583
76584    function getSetQuarter (input) {
76585        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
76586    }
76587
76588    // FORMATTING
76589
76590    addFormatToken('D', ['DD', 2], 'Do', 'date');
76591
76592    // ALIASES
76593
76594    addUnitAlias('date', 'D');
76595
76596    // PRIORITY
76597    addUnitPriority('date', 9);
76598
76599    // PARSING
76600
76601    addRegexToken('D',  match1to2);
76602    addRegexToken('DD', match1to2, match2);
76603    addRegexToken('Do', function (isStrict, locale) {
76604        // TODO: Remove "ordinalParse" fallback in next major release.
76605        return isStrict ?
76606          (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
76607          locale._dayOfMonthOrdinalParseLenient;
76608    });
76609
76610    addParseToken(['D', 'DD'], DATE);
76611    addParseToken('Do', function (input, array) {
76612        array[DATE] = toInt(input.match(match1to2)[0]);
76613    });
76614
76615    // MOMENTS
76616
76617    var getSetDayOfMonth = makeGetSet('Date', true);
76618
76619    // FORMATTING
76620
76621    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
76622
76623    // ALIASES
76624
76625    addUnitAlias('dayOfYear', 'DDD');
76626
76627    // PRIORITY
76628    addUnitPriority('dayOfYear', 4);
76629
76630    // PARSING
76631
76632    addRegexToken('DDD',  match1to3);
76633    addRegexToken('DDDD', match3);
76634    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
76635        config._dayOfYear = toInt(input);
76636    });
76637
76638    // HELPERS
76639
76640    // MOMENTS
76641
76642    function getSetDayOfYear (input) {
76643        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
76644        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
76645    }
76646
76647    // FORMATTING
76648
76649    addFormatToken('m', ['mm', 2], 0, 'minute');
76650
76651    // ALIASES
76652
76653    addUnitAlias('minute', 'm');
76654
76655    // PRIORITY
76656
76657    addUnitPriority('minute', 14);
76658
76659    // PARSING
76660
76661    addRegexToken('m',  match1to2);
76662    addRegexToken('mm', match1to2, match2);
76663    addParseToken(['m', 'mm'], MINUTE);
76664
76665    // MOMENTS
76666
76667    var getSetMinute = makeGetSet('Minutes', false);
76668
76669    // FORMATTING
76670
76671    addFormatToken('s', ['ss', 2], 0, 'second');
76672
76673    // ALIASES
76674
76675    addUnitAlias('second', 's');
76676
76677    // PRIORITY
76678
76679    addUnitPriority('second', 15);
76680
76681    // PARSING
76682
76683    addRegexToken('s',  match1to2);
76684    addRegexToken('ss', match1to2, match2);
76685    addParseToken(['s', 'ss'], SECOND);
76686
76687    // MOMENTS
76688
76689    var getSetSecond = makeGetSet('Seconds', false);
76690
76691    // FORMATTING
76692
76693    addFormatToken('S', 0, 0, function () {
76694        return ~~(this.millisecond() / 100);
76695    });
76696
76697    addFormatToken(0, ['SS', 2], 0, function () {
76698        return ~~(this.millisecond() / 10);
76699    });
76700
76701    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
76702    addFormatToken(0, ['SSSS', 4], 0, function () {
76703        return this.millisecond() * 10;
76704    });
76705    addFormatToken(0, ['SSSSS', 5], 0, function () {
76706        return this.millisecond() * 100;
76707    });
76708    addFormatToken(0, ['SSSSSS', 6], 0, function () {
76709        return this.millisecond() * 1000;
76710    });
76711    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
76712        return this.millisecond() * 10000;
76713    });
76714    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
76715        return this.millisecond() * 100000;
76716    });
76717    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
76718        return this.millisecond() * 1000000;
76719    });
76720
76721
76722    // ALIASES
76723
76724    addUnitAlias('millisecond', 'ms');
76725
76726    // PRIORITY
76727
76728    addUnitPriority('millisecond', 16);
76729
76730    // PARSING
76731
76732    addRegexToken('S',    match1to3, match1);
76733    addRegexToken('SS',   match1to3, match2);
76734    addRegexToken('SSS',  match1to3, match3);
76735
76736    var token;
76737    for (token = 'SSSS'; token.length <= 9; token += 'S') {
76738        addRegexToken(token, matchUnsigned);
76739    }
76740
76741    function parseMs(input, array) {
76742        array[MILLISECOND] = toInt(('0.' + input) * 1000);
76743    }
76744
76745    for (token = 'S'; token.length <= 9; token += 'S') {
76746        addParseToken(token, parseMs);
76747    }
76748    // MOMENTS
76749
76750    var getSetMillisecond = makeGetSet('Milliseconds', false);
76751
76752    // FORMATTING
76753
76754    addFormatToken('z',  0, 0, 'zoneAbbr');
76755    addFormatToken('zz', 0, 0, 'zoneName');
76756
76757    // MOMENTS
76758
76759    function getZoneAbbr () {
76760        return this._isUTC ? 'UTC' : '';
76761    }
76762
76763    function getZoneName () {
76764        return this._isUTC ? 'Coordinated Universal Time' : '';
76765    }
76766
76767    var proto = Moment.prototype;
76768
76769    proto.add               = add;
76770    proto.calendar          = calendar$1;
76771    proto.clone             = clone;
76772    proto.diff              = diff;
76773    proto.endOf             = endOf;
76774    proto.format            = format;
76775    proto.from              = from;
76776    proto.fromNow           = fromNow;
76777    proto.to                = to;
76778    proto.toNow             = toNow;
76779    proto.get               = stringGet;
76780    proto.invalidAt         = invalidAt;
76781    proto.isAfter           = isAfter;
76782    proto.isBefore          = isBefore;
76783    proto.isBetween         = isBetween;
76784    proto.isSame            = isSame;
76785    proto.isSameOrAfter     = isSameOrAfter;
76786    proto.isSameOrBefore    = isSameOrBefore;
76787    proto.isValid           = isValid$2;
76788    proto.lang              = lang;
76789    proto.locale            = locale;
76790    proto.localeData        = localeData;
76791    proto.max               = prototypeMax;
76792    proto.min               = prototypeMin;
76793    proto.parsingFlags      = parsingFlags;
76794    proto.set               = stringSet;
76795    proto.startOf           = startOf;
76796    proto.subtract          = subtract;
76797    proto.toArray           = toArray;
76798    proto.toObject          = toObject;
76799    proto.toDate            = toDate;
76800    proto.toISOString       = toISOString;
76801    proto.inspect           = inspect;
76802    proto.toJSON            = toJSON;
76803    proto.toString          = toString;
76804    proto.unix              = unix;
76805    proto.valueOf           = valueOf;
76806    proto.creationData      = creationData;
76807    proto.year       = getSetYear;
76808    proto.isLeapYear = getIsLeapYear;
76809    proto.weekYear    = getSetWeekYear;
76810    proto.isoWeekYear = getSetISOWeekYear;
76811    proto.quarter = proto.quarters = getSetQuarter;
76812    proto.month       = getSetMonth;
76813    proto.daysInMonth = getDaysInMonth;
76814    proto.week           = proto.weeks        = getSetWeek;
76815    proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
76816    proto.weeksInYear    = getWeeksInYear;
76817    proto.isoWeeksInYear = getISOWeeksInYear;
76818    proto.date       = getSetDayOfMonth;
76819    proto.day        = proto.days             = getSetDayOfWeek;
76820    proto.weekday    = getSetLocaleDayOfWeek;
76821    proto.isoWeekday = getSetISODayOfWeek;
76822    proto.dayOfYear  = getSetDayOfYear;
76823    proto.hour = proto.hours = getSetHour;
76824    proto.minute = proto.minutes = getSetMinute;
76825    proto.second = proto.seconds = getSetSecond;
76826    proto.millisecond = proto.milliseconds = getSetMillisecond;
76827    proto.utcOffset            = getSetOffset;
76828    proto.utc                  = setOffsetToUTC;
76829    proto.local                = setOffsetToLocal;
76830    proto.parseZone            = setOffsetToParsedOffset;
76831    proto.hasAlignedHourOffset = hasAlignedHourOffset;
76832    proto.isDST                = isDaylightSavingTime;
76833    proto.isLocal              = isLocal;
76834    proto.isUtcOffset          = isUtcOffset;
76835    proto.isUtc                = isUtc;
76836    proto.isUTC                = isUtc;
76837    proto.zoneAbbr = getZoneAbbr;
76838    proto.zoneName = getZoneName;
76839    proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
76840    proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
76841    proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
76842    proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
76843    proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
76844
76845    function createUnix (input) {
76846        return createLocal(input * 1000);
76847    }
76848
76849    function createInZone () {
76850        return createLocal.apply(null, arguments).parseZone();
76851    }
76852
76853    function preParsePostFormat (string) {
76854        return string;
76855    }
76856
76857    var proto$1 = Locale.prototype;
76858
76859    proto$1.calendar        = calendar;
76860    proto$1.longDateFormat  = longDateFormat;
76861    proto$1.invalidDate     = invalidDate;
76862    proto$1.ordinal         = ordinal;
76863    proto$1.preparse        = preParsePostFormat;
76864    proto$1.postformat      = preParsePostFormat;
76865    proto$1.relativeTime    = relativeTime;
76866    proto$1.pastFuture      = pastFuture;
76867    proto$1.set             = set;
76868
76869    proto$1.months            =        localeMonths;
76870    proto$1.monthsShort       =        localeMonthsShort;
76871    proto$1.monthsParse       =        localeMonthsParse;
76872    proto$1.monthsRegex       = monthsRegex;
76873    proto$1.monthsShortRegex  = monthsShortRegex;
76874    proto$1.week = localeWeek;
76875    proto$1.firstDayOfYear = localeFirstDayOfYear;
76876    proto$1.firstDayOfWeek = localeFirstDayOfWeek;
76877
76878    proto$1.weekdays       =        localeWeekdays;
76879    proto$1.weekdaysMin    =        localeWeekdaysMin;
76880    proto$1.weekdaysShort  =        localeWeekdaysShort;
76881    proto$1.weekdaysParse  =        localeWeekdaysParse;
76882
76883    proto$1.weekdaysRegex       =        weekdaysRegex;
76884    proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
76885    proto$1.weekdaysMinRegex    =        weekdaysMinRegex;
76886
76887    proto$1.isPM = localeIsPM;
76888    proto$1.meridiem = localeMeridiem;
76889
76890    function get$1 (format, index, field, setter) {
76891        var locale = getLocale();
76892        var utc = createUTC().set(setter, index);
76893        return locale[field](utc, format);
76894    }
76895
76896    function listMonthsImpl (format, index, field) {
76897        if (isNumber(format)) {
76898            index = format;
76899            format = undefined;
76900        }
76901
76902        format = format || '';
76903
76904        if (index != null) {
76905            return get$1(format, index, field, 'month');
76906        }
76907
76908        var i;
76909        var out = [];
76910        for (i = 0; i < 12; i++) {
76911            out[i] = get$1(format, i, field, 'month');
76912        }
76913        return out;
76914    }
76915
76916    // ()
76917    // (5)
76918    // (fmt, 5)
76919    // (fmt)
76920    // (true)
76921    // (true, 5)
76922    // (true, fmt, 5)
76923    // (true, fmt)
76924    function listWeekdaysImpl (localeSorted, format, index, field) {
76925        if (typeof localeSorted === 'boolean') {
76926            if (isNumber(format)) {
76927                index = format;
76928                format = undefined;
76929            }
76930
76931            format = format || '';
76932        } else {
76933            format = localeSorted;
76934            index = format;
76935            localeSorted = false;
76936
76937            if (isNumber(format)) {
76938                index = format;
76939                format = undefined;
76940            }
76941
76942            format = format || '';
76943        }
76944
76945        var locale = getLocale(),
76946            shift = localeSorted ? locale._week.dow : 0;
76947
76948        if (index != null) {
76949            return get$1(format, (index + shift) % 7, field, 'day');
76950        }
76951
76952        var i;
76953        var out = [];
76954        for (i = 0; i < 7; i++) {
76955            out[i] = get$1(format, (i + shift) % 7, field, 'day');
76956        }
76957        return out;
76958    }
76959
76960    function listMonths (format, index) {
76961        return listMonthsImpl(format, index, 'months');
76962    }
76963
76964    function listMonthsShort (format, index) {
76965        return listMonthsImpl(format, index, 'monthsShort');
76966    }
76967
76968    function listWeekdays (localeSorted, format, index) {
76969        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
76970    }
76971
76972    function listWeekdaysShort (localeSorted, format, index) {
76973        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
76974    }
76975
76976    function listWeekdaysMin (localeSorted, format, index) {
76977        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
76978    }
76979
76980    getSetGlobalLocale('en', {
76981        dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
76982        ordinal : function (number) {
76983            var b = number % 10,
76984                output = (toInt(number % 100 / 10) === 1) ? 'th' :
76985                (b === 1) ? 'st' :
76986                (b === 2) ? 'nd' :
76987                (b === 3) ? 'rd' : 'th';
76988            return number + output;
76989        }
76990    });
76991
76992    // Side effect imports
76993
76994    hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
76995    hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
76996
76997    var mathAbs = Math.abs;
76998
76999    function abs () {
77000        var data           = this._data;
77001
77002        this._milliseconds = mathAbs(this._milliseconds);
77003        this._days         = mathAbs(this._days);
77004        this._months       = mathAbs(this._months);
77005
77006        data.milliseconds  = mathAbs(data.milliseconds);
77007        data.seconds       = mathAbs(data.seconds);
77008        data.minutes       = mathAbs(data.minutes);
77009        data.hours         = mathAbs(data.hours);
77010        data.months        = mathAbs(data.months);
77011        data.years         = mathAbs(data.years);
77012
77013        return this;
77014    }
77015
77016    function addSubtract$1 (duration, input, value, direction) {
77017        var other = createDuration(input, value);
77018
77019        duration._milliseconds += direction * other._milliseconds;
77020        duration._days         += direction * other._days;
77021        duration._months       += direction * other._months;
77022
77023        return duration._bubble();
77024    }
77025
77026    // supports only 2.0-style add(1, 's') or add(duration)
77027    function add$1 (input, value) {
77028        return addSubtract$1(this, input, value, 1);
77029    }
77030
77031    // supports only 2.0-style subtract(1, 's') or subtract(duration)
77032    function subtract$1 (input, value) {
77033        return addSubtract$1(this, input, value, -1);
77034    }
77035
77036    function absCeil (number) {
77037        if (number < 0) {
77038            return Math.floor(number);
77039        } else {
77040            return Math.ceil(number);
77041        }
77042    }
77043
77044    function bubble () {
77045        var milliseconds = this._milliseconds;
77046        var days         = this._days;
77047        var months       = this._months;
77048        var data         = this._data;
77049        var seconds, minutes, hours, years, monthsFromDays;
77050
77051        // if we have a mix of positive and negative values, bubble down first
77052        // check: https://github.com/moment/moment/issues/2166
77053        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
77054                (milliseconds <= 0 && days <= 0 && months <= 0))) {
77055            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
77056            days = 0;
77057            months = 0;
77058        }
77059
77060        // The following code bubbles up values, see the tests for
77061        // examples of what that means.
77062        data.milliseconds = milliseconds % 1000;
77063
77064        seconds           = absFloor(milliseconds / 1000);
77065        data.seconds      = seconds % 60;
77066
77067        minutes           = absFloor(seconds / 60);
77068        data.minutes      = minutes % 60;
77069
77070        hours             = absFloor(minutes / 60);
77071        data.hours        = hours % 24;
77072
77073        days += absFloor(hours / 24);
77074
77075        // convert days to months
77076        monthsFromDays = absFloor(daysToMonths(days));
77077        months += monthsFromDays;
77078        days -= absCeil(monthsToDays(monthsFromDays));
77079
77080        // 12 months -> 1 year
77081        years = absFloor(months / 12);
77082        months %= 12;
77083
77084        data.days   = days;
77085        data.months = months;
77086        data.years  = years;
77087
77088        return this;
77089    }
77090
77091    function daysToMonths (days) {
77092        // 400 years have 146097 days (taking into account leap year rules)
77093        // 400 years have 12 months === 4800
77094        return days * 4800 / 146097;
77095    }
77096
77097    function monthsToDays (months) {
77098        // the reverse of daysToMonths
77099        return months * 146097 / 4800;
77100    }
77101
77102    function as (units) {
77103        if (!this.isValid()) {
77104            return NaN;
77105        }
77106        var days;
77107        var months;
77108        var milliseconds = this._milliseconds;
77109
77110        units = normalizeUnits(units);
77111
77112        if (units === 'month' || units === 'quarter' || units === 'year') {
77113            days = this._days + milliseconds / 864e5;
77114            months = this._months + daysToMonths(days);
77115            switch (units) {
77116                case 'month':   return months;
77117                case 'quarter': return months / 3;
77118                case 'year':    return months / 12;
77119            }
77120        } else {
77121            // handle milliseconds separately because of floating point math errors (issue #1867)
77122            days = this._days + Math.round(monthsToDays(this._months));
77123            switch (units) {
77124                case 'week'   : return days / 7     + milliseconds / 6048e5;
77125                case 'day'    : return days         + milliseconds / 864e5;
77126                case 'hour'   : return days * 24    + milliseconds / 36e5;
77127                case 'minute' : return days * 1440  + milliseconds / 6e4;
77128                case 'second' : return days * 86400 + milliseconds / 1000;
77129                // Math.floor prevents floating point math errors here
77130                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
77131                default: throw new Error('Unknown unit ' + units);
77132            }
77133        }
77134    }
77135
77136    // TODO: Use this.as('ms')?
77137    function valueOf$1 () {
77138        if (!this.isValid()) {
77139            return NaN;
77140        }
77141        return (
77142            this._milliseconds +
77143            this._days * 864e5 +
77144            (this._months % 12) * 2592e6 +
77145            toInt(this._months / 12) * 31536e6
77146        );
77147    }
77148
77149    function makeAs (alias) {
77150        return function () {
77151            return this.as(alias);
77152        };
77153    }
77154
77155    var asMilliseconds = makeAs('ms');
77156    var asSeconds      = makeAs('s');
77157    var asMinutes      = makeAs('m');
77158    var asHours        = makeAs('h');
77159    var asDays         = makeAs('d');
77160    var asWeeks        = makeAs('w');
77161    var asMonths       = makeAs('M');
77162    var asQuarters     = makeAs('Q');
77163    var asYears        = makeAs('y');
77164
77165    function clone$1 () {
77166        return createDuration(this);
77167    }
77168
77169    function get$2 (units) {
77170        units = normalizeUnits(units);
77171        return this.isValid() ? this[units + 's']() : NaN;
77172    }
77173
77174    function makeGetter(name) {
77175        return function () {
77176            return this.isValid() ? this._data[name] : NaN;
77177        };
77178    }
77179
77180    var milliseconds = makeGetter('milliseconds');
77181    var seconds      = makeGetter('seconds');
77182    var minutes      = makeGetter('minutes');
77183    var hours        = makeGetter('hours');
77184    var days         = makeGetter('days');
77185    var months       = makeGetter('months');
77186    var years        = makeGetter('years');
77187
77188    function weeks () {
77189        return absFloor(this.days() / 7);
77190    }
77191
77192    var round = Math.round;
77193    var thresholds = {
77194        ss: 44,         // a few seconds to seconds
77195        s : 45,         // seconds to minute
77196        m : 45,         // minutes to hour
77197        h : 22,         // hours to day
77198        d : 26,         // days to month
77199        M : 11          // months to year
77200    };
77201
77202    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
77203    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
77204        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
77205    }
77206
77207    function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
77208        var duration = createDuration(posNegDuration).abs();
77209        var seconds  = round(duration.as('s'));
77210        var minutes  = round(duration.as('m'));
77211        var hours    = round(duration.as('h'));
77212        var days     = round(duration.as('d'));
77213        var months   = round(duration.as('M'));
77214        var years    = round(duration.as('y'));
77215
77216        var a = seconds <= thresholds.ss && ['s', seconds]  ||
77217                seconds < thresholds.s   && ['ss', seconds] ||
77218                minutes <= 1             && ['m']           ||
77219                minutes < thresholds.m   && ['mm', minutes] ||
77220                hours   <= 1             && ['h']           ||
77221                hours   < thresholds.h   && ['hh', hours]   ||
77222                days    <= 1             && ['d']           ||
77223                days    < thresholds.d   && ['dd', days]    ||
77224                months  <= 1             && ['M']           ||
77225                months  < thresholds.M   && ['MM', months]  ||
77226                years   <= 1             && ['y']           || ['yy', years];
77227
77228        a[2] = withoutSuffix;
77229        a[3] = +posNegDuration > 0;
77230        a[4] = locale;
77231        return substituteTimeAgo.apply(null, a);
77232    }
77233
77234    // This function allows you to set the rounding function for relative time strings
77235    function getSetRelativeTimeRounding (roundingFunction) {
77236        if (roundingFunction === undefined) {
77237            return round;
77238        }
77239        if (typeof(rou
77239ndingFunction) === 'function') {
77240            round = roundingFunction;
77241            return true;
77242        }
77243        return false;
77244    }
77245
77246    // This function allows you to set a threshold for relative time strings
77247    function getSetRelativeTimeThreshold (threshold, limit) {
77248        if (thresholds[threshold] === undefined) {
77249            return false;
77250        }
77251        if (limit === undefined) {
77252            return thresholds[threshold];
77253        }
77254        thresholds[threshold] = limit;
77255        if (threshold === 's') {
77256            thresholds.ss = limit - 1;
77257        }
77258        return true;
77259    }
77260
77261    function humanize (withSuffix) {
77262        if (!this.isValid()) {
77263            return this.localeData().invalidDate();
77264        }
77265
77266        var locale = this.localeData();
77267        var output = relativeTime$1(this, !withSuffix, locale);
77268
77269        if (withSuffix) {
77270            output = locale.pastFuture(+this, output);
77271        }
77272
77273        return locale.postformat(output);
77274    }
77275
77276    var abs$1 = Math.abs;
77277
77278    function sign(x) {
77279        return ((x > 0) - (x < 0)) || +x;
77280    }
77281
77282    function toISOString$1() {
77283        // for ISO strings we do not use the normal bubbling rules:
77284        //  * milliseconds bubble up until they become hours
77285        //  * days do not bubble at all
77286        //  * months bubble up until they become years
77287        // This is because there is no context-free conversion between hours and days
77288        // (think of clock changes)
77289        // and also not between days and months (28-31 days per month)
77290        if (!this.isValid()) {
77291            return this.localeData().invalidDate();
77292        }
77293
77294        var seconds = abs$1(this._milliseconds) / 1000;
77295        var days         = abs$1(this._days);
77296        var months       = abs$1(this._months);
77297        var minutes, hours, years;
77298
77299        // 3600 seconds -> 60 minutes -> 1 hour
77300        minutes           = absFloor(seconds / 60);
77301        hours             = absFloor(minutes / 60);
77302        seconds %= 60;
77303        minutes %= 60;
77304
77305        // 12 months -> 1 year
77306        years  = absFloor(months / 12);
77307        months %= 12;
77308
77309
77310        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
77311        var Y = years;
77312        var M = months;
77313        var D = days;
77314        var h = hours;
77315        var m = minutes;
77316        var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
77317        var total = this.asSeconds();
77318
77319        if (!total) {
77320            // this is the same as C#'s (Noda) and python (isodate)...
77321            // but not other JS (goog.date)
77322            return 'P0D';
77323        }
77324
77325        var totalSign = total < 0 ? '-' : '';
77326        var ymSign = sign(this._months) !== sign(total) ? '-' : '';
77327        var daysSign = sign(this._days) !== sign(total) ? '-' : '';
77328        var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
77329
77330        return totalSign + 'P' +
77331            (Y ? ymSign + Y + 'Y' : '') +
77332            (M ? ymSign + M + 'M' : '') +
77333            (D ? daysSign + D + 'D' : '') +
77334            ((h || m || s) ? 'T' : '') +
77335            (h ? hmsSign + h + 'H' : '') +
77336            (m ? hmsSign + m + 'M' : '') +
77337            (s ? hmsSign + s + 'S' : '');
77338    }
77339
77340    var proto$2 = Duration.prototype;
77341
77342    proto$2.isValid        = isValid$1;
77343    proto$2.abs            = abs;
77344    proto$2.add            = add$1;
77345    proto$2.subtract       = subtract$1;
77346    proto$2.as             = as;
77347    proto$2.asMilliseconds = asMilliseconds;
77348    proto$2.asSeconds      = asSeconds;
77349    proto$2.asMinutes      = asMinutes;
77350    proto$2.asHours        = asHours;
77351    proto$2.asDays         = asDays;
77352    proto$2.asWeeks        = asWeeks;
77353    proto$2.asMonths       = asMonths;
77354    proto$2.asQuarters     = asQuarters;
77355    proto$2.asYears        = asYears;
77356    proto$2.valueOf        = valueOf$1;
77357    proto$2._bubble        = bubble;
77358    proto$2.clone          = clone$1;
77359    proto$2.get            = get$2;
77360    proto$2.milliseconds   = milliseconds;
77361    proto$2.seconds        = seconds;
77362    proto$2.minutes        = minutes;
77363    proto$2.hours          = hours;
77364    proto$2.days           = days;
77365    proto$2.weeks          = weeks;
77366    proto$2.months         = months;
77367    proto$2.years          = years;
77368    proto$2.humanize       = humanize;
77369    proto$2.toISOString    = toISOString$1;
77370    proto$2.toString       = toISOString$1;
77371    proto$2.toJSON         = toISOString$1;
77372    proto$2.locale         = locale;
77373    proto$2.localeData     = localeData;
77374
77375    proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
77376    proto$2.lang = lang;
77377
77378    // Side effect imports
77379
77380    // FORMATTING
77381
77382    addFormatToken('X', 0, 0, 'unix');
77383    addFormatToken('x', 0, 0, 'valueOf');
77384
77385    // PARSING
77386
77387    addRegexToken('x', matchSigned);
77388    addRegexToken('X', matchTimestamp);
77389    addParseToken('X', function (input, array, config) {
77390        config._d = new Date(parseFloat(input, 10) * 1000);
77391    });
77392    addParseToken('x', function (input, array, config) {
77393        config._d = new Date(toInt(input));
77394    });
77395
77396    // Side effect imports
77397
77398
77399    hooks.version = '2.24.0';
77400
77401    setHookCallback(createLocal);
77402
77403    hooks.fn                    = proto;
77404    hooks.min                   = min;
77405    hooks.max                   = max;
77406    hooks.now                   = now;
77407    hooks.utc                   = createUTC;
77408    hooks.unix                  = createUnix;
77409    hooks.months                = listMonths;
77410    hooks.isDate                = isDate;
77411    hooks.locale                = getSetGlobalLocale;
77412    hooks.invalid               = createInvalid;
77413    hooks.duration              = createDuration;
77414    hooks.isMoment              = isMoment;
77415    hooks.weekdays              = listWeekdays;
77416    hooks.parseZone             = createInZone;
77417    hooks.localeData            = getLocale;
77418    hooks.isDuration            = isDuration;
77419    hooks.monthsShort           = listMonthsShort;
77420    hooks.weekdaysMin           = listWeekdaysMin;
77421    hooks.defineLocale          = defineLocale;
77422    hooks.updateLocale          = updateLocale;
77423    hooks.locales               = listLocales;
77424    hooks.weekdaysShort         = listWeekdaysShort;
77425    hooks.normalizeUnits        = normalizeUnits;
77426    hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
77427    hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
77428    hooks.calendarFormat        = getCalendarFormat;
77429    hooks.prototype             = proto;
77430
77431    // currently HTML5 input type only supports 24-hour formats
77432    hooks.HTML5_FMT = {
77433        DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',             // <input type="datetime-local" />
77434        DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',  // <input type="datetime-local" step="1" />
77435        DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',   // <input type="datetime-local" step="0.001" />
77436        DATE: 'YYYY-MM-DD',                             // <input type="date" />
77437        TIME: 'HH:mm',                                  // <input type="time" />
77438        TIME_SECONDS: 'HH:mm:ss',                       // <input type="time" step="1" />
77439        TIME_MS: 'HH:mm:ss.SSS',                        // <input type="time" step="0.001" />
77440        WEEK: 'GGGG-[W]WW',                             // <input type="week" />
77441        MONTH: 'YYYY-MM'                                // <input type="month" />
77442    };
77443
77444    return hooks;
77445
77446})));
77447});
77448
77449var FORMATS = {
77450	datetime: 'MMM D, YYYY, h:mm:ss a',
77451	millisecond: 'h:mm:ss.SSS a',
77452	second: 'h:mm:ss a',
77453	minute: 'h:mm a',
77454	hour: 'hA',
77455	day: 'MMM D',
77456	week: 'll',
77457	month: 'MMM YYYY',
77458	quarter: '[Q]Q - YYYY',
77459	year: 'YYYY'
77460};
77461
77462core_adapters._date.override(typeof moment === 'function' ? {
77463	_id: 'moment', // DEBUG ONLY
77464
77465	formats: function() {
77466		return FORMATS;
77467	},
77468
77469	parse: function(value, format) {
77470		if (typeof value === 'string' && typeof format === 'string') {
77471			value = moment(value, format);
77472		} else if (!(value instanceof moment)) {
77473			value = moment(value);
77474		}
77475		return value.isValid() ? value.valueOf() : null;
77476	},
77477
77478	format: function(time, format) {
77479		return moment(time).format(format);
77480	},
77481
77482	add: function(time, amount, unit) {
77483		return moment(time).add(amount, unit).valueOf();
77484	},
77485
77486	diff: function(max, min, unit) {
77487		return moment.duration(moment(max).diff(moment(min))).as(unit);
77488	},
77489
77490	startOf: function(time, unit, weekday) {
77491		time = moment(time);
77492		if (unit === 'isoWeek') {
77493			return time.isoWeekday(weekday).valueOf();
77494		}
77495		return time.startOf(unit).valueOf();
77496	},
77497
77498	endOf: function(time, unit) {
77499		return moment(time).endOf(unit).valueOf();
77500	},
77501
77502	// DEPRECATIONS
77503
77504	/**
77505	 * Provided for backward compatibility with scale.getValueForPixel().
77506	 * @deprecated since version 2.8.0
77507	 * @todo remove at version 3
77508	 * @private
77509	 */
77510	_create: function(time) {
77511		return moment(time);
77512	},
77513} : {});
77514
77515core_defaults._set('global', {
77516	plugins: {
77517		filler: {
77518			propagate: true
77519		}
77520	}
77521});
77522
77523var mappers = {
77524	dataset: function(source) {
77525		var index = source.fill;
77526		var chart = source.chart;
77527		var meta = chart.getDatasetMeta(index);
77528		var visible = meta && chart.isDatasetVisible(index);
77529		var points = (visible && meta.dataset._children) || [];
77530		var length = points.length || 0;
77531
77532		return !length ? null : function(point, i) {
77533			return (i < length && points[i]._view) || null;
77534		};
77535	},
77536
vendor: 4,419 bytes, lines 77537-77764
77537	boundary: function(source) {
77538		var boundary = source.boundary;
77539		var x = boundary ? boundary.x : null;
77540		var y = boundary ? boundary.y : null;
77541
77542		return function(point) {
77543			return {
77544				x: x === null ? point.x : x,
77545				y: y === null ? point.y : y,
77546			};
77547		};
77548	}
77549};
77550
77551// @todo if (fill[0] === '#')
77552function decodeFill(el, index, count) {
77553	var model = el._model || {};
77554	var fill = model.fill;
77555	var target;
77556
77557	if (fill === undefined) {
77558		fill = !!model.backgroundColor;
77559	}
77560
77561	if (fill === false || fill === null) {
77562		return false;
77563	}
77564
77565	if (fill === true) {
77566		return 'origin';
77567	}
77568
77569	target = parseFloat(fill, 10);
77570	if (isFinite(target) && Math.floor(target) === target) {
77571		if (fill[0] === '-' || fill[0] === '+') {
77572			target = index + target;
77573		}
77574
77575		if (target === index || target < 0 || target >= count) {
77576			return false;
77577		}
77578
77579		return target;
77580	}
77581
77582	switch (fill) {
77583	// compatibility
77584	case 'bottom':
77585		return 'start';
77586	case 'top':
77587		return 'end';
77588	case 'zero':
77589		return 'origin';
77590	// supported boundaries
77591	case 'origin':
77592	case 'start':
77593	case 'end':
77594		return fill;
77595	// invalid fill values
77596	default:
77597		return false;
77598	}
77599}
77600
77601function computeBoundary(source) {
77602	var model = source.el._model || {};
77603	var scale = source.el._scale || {};
77604	var fill = source.fill;
77605	var target = null;
77606	var horizontal;
77607
77608	if (isFinite(fill)) {
77609		return null;
77610	}
77611
77612	// Backward compatibility: until v3, we still need to support boundary values set on
77613	// the model (scaleTop, scaleBottom and scaleZero) because some external plugins and
77614	// controllers might still use it (e.g. the Smith chart).
77615
77616	if (fill === 'start') {
77617		target = model.scaleBottom === undefined ? scale.bottom : model.scaleBottom;
77618	} else if (fill === 'end') {
77619		target = model.scaleTop === undefined ? scale.top : model.scaleTop;
77620	} else if (model.scaleZero !== undefined) {
77621		target = model.scaleZero;
77622	} else if (scale.getBasePosition) {
77623		target = scale.getBasePosition();
77624	} else if (scale.getBasePixel) {
77625		target = scale.getBasePixel();
77626	}
77627
77628	if (target !== undefined && target !== null) {
77629		if (target.x !== undefined && target.y !== undefined) {
77630			return target;
77631		}
77632
77633		if (helpers$1.isFinite(target)) {
77634			horizontal = scale.isHorizontal();
77635			return {
77636				x: horizontal ? target : null,
77637				y: horizontal ? null : target
77638			};
77639		}
77640	}
77641
77642	return null;
77643}
77644
77645function resolveTarget(sources, index, propagate) {
77646	var source = sources[index];
77647	var fill = source.fill;
77648	var visited = [index];
77649	var target;
77650
77651	if (!propagate) {
77652		return fill;
77653	}
77654
77655	while (fill !== false && visited.indexOf(fill) === -1) {
77656		if (!isFinite(fill)) {
77657			return fill;
77658		}
77659
77660		target = sources[fill];
77661		if (!target) {
77662			return false;
77663		}
77664
77665		if (target.visible) {
77666			return fill;
77667		}
77668
77669		visited.push(fill);
77670		fill = target.fill;
77671	}
77672
77673	return false;
77674}
77675
77676function createMapper(source) {
77677	var fill = source.fill;
77678	var type = 'dataset';
77679
77680	if (fill === false) {
77681		return null;
77682	}
77683
77684	if (!isFinite(fill)) {
77685		type = 'boundary';
77686	}
77687
77688	return mappers[type](source);
77689}
77690
77691function isDrawable(point) {
77692	return point && !point.skip;
77693}
77694
77695function drawArea(ctx, curve0, curve1, len0, len1) {
77696	var i;
77697
77698	if (!len0 || !len1) {
77699		return;
77700	}
77701
77702	// building first area curve (normal)
77703	ctx.moveTo(curve0[0].x, curve0[0].y);
77704	for (i = 1; i < len0; ++i) {
77705		helpers$1.canvas.lineTo(ctx, curve0[i - 1], curve0[i]);
77706	}
77707
77708	// joining the two area curves
77709	ctx.lineTo(curve1[len1 - 1].x, curve1[len1 - 1].y);
77710
77711	// building opposite area curve (reverse)
77712	for (i = len1 - 1; i > 0; --i) {
77713		helpers$1.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true);
77714	}
77715}
77716
77717function doFill(ctx, points, mapper, view, color, loop) {
77718	var count = points.length;
77719	var span = view.spanGaps;
77720	var curve0 = [];
77721	var curve1 = [];
77722	var len0 = 0;
77723	var len1 = 0;
77724	var i, ilen, index, p0, p1, d0, d1;
77725
77726	ctx.beginPath();
77727
77728	for (i = 0, ilen = (count + !!loop); i < ilen; ++i) {
77729		index = i % count;
77730		p0 = points[index]._view;
77731		p1 = mapper(p0, index, view);
77732		d0 = isDrawable(p0);
77733		d1 = isDrawable(p1);
77734
77735		if (d0 && d1) {
77736			len0 = curve0.push(p0);
77737			len1 = curve1.push(p1);
77738		} else if (len0 && len1) {
77739			if (!span) {
77740				drawArea(ctx, curve0, curve1, len0, len1);
77741				len0 = len1 = 0;
77742				curve0 = [];
77743				curve1 = [];
77744			} else {
77745				if (d0) {
77746					curve0.push(p0);
77747				}
77748				if (d1) {
77749					curve1.push(p1);
77750				}
77751			}
77752		}
77753	}
77754
77755	drawArea(ctx, curve0, curve1, len0, len1);
77756
77757	ctx.closePath();
77758	ctx.fillStyle = color;
77759	ctx.fill();
77760}
77761
77762var plugin_filler = {
77763	id: 'filler',
77764
77765	afterDatasetsUpdate: function(chart, options) {
77766		var count = (chart.data.datasets || []).length;
77767		var propagate = options.propagate;
77768		var sources = [];
77769		var meta, i, el, source;
77770
77771		for (i = 0; i < count; ++i) {
77772			meta = chart.getDatasetMeta(i);
77773			el = meta.dataset;
77774			source = null;
77775
77776			if (el && el._model && el instanceof elements.Line) {
77777				source = {
77778					visible: chart.isDatasetVisible(i),
77779					fill: decodeFill(el, i, count),
77780					chart: chart,
77781					el: el
77782				};
77783			}
77784
77785			meta.$filler = source;
77786			sources.push(source);
77787		}
77788
77789		for (i = 0; i < count; ++i) {
77790			source = sources[i];
77791			if (!source) {
77792				continue;
77793			}
77794
77795			source.fill = resolveTarget(sources, i, propagate);
77796			source.boundary = computeBoundary(source);
77797			source.mapper = createMapper(source);
77798		}
77799	},
77800
77801	beforeDatasetDraw: function(chart, args) {
77802		var meta = args.meta.$filler;
77803		if (!meta) {
77804			return;
77805		}
77806
77807		var ctx = chart.ctx;
77808		var el = meta.el;
77809		var view = el._view;
77810		var points = el._children || [];
77811		var mapper = meta.mapper;
77812		var color = view.backgroundColor || core_defaults.global.defaultColor;
77813
77814		if (mapper && color && points.length) {
77815			helpers$1.canvas.clipArea(ctx, chart.chartArea);
77816			doFill(ctx, points, mapper, view, color, el._loop);
77817			helpers$1.canvas.unclipArea(ctx);
77818		}
77819	}
77820};
77821
77822var noop$1 = helpers$1.noop;
77823var valueOrDefault$d = helpers$1.valueOrDefault;
77824
77825core_defaults._set('global', {
77826	legend: {
77827		display: true,
77828		position: 'top',
77829		fullWidth: true,
77830		reverse: false,
77831		weight: 1000,
77832
77833		// a callback that will handle
77834		onClick: function(e, legendItem) {
77835			var index = legendItem.datasetIndex;
77836			var ci = this.chart;
77837			var meta = ci.getDatasetMeta(index);
77838
77839			// See controller.isDatasetVisible comment
77840			meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
77841
77842			// We hid a dataset ... rerender the chart
77843			ci.update();
77844		},
77845
77846		onHover: null,
77847		onLeave: null,
77848
77849		labels: {
77850			boxWidth: 40,
77851			padding: 10,
77852			// Generates labels shown in the legend
77853			// Valid properties to return:
77854			// text : text to display
77855			// fillStyle : fill of coloured box
77856			// strokeStyle: stroke of coloured box
77857			// hidden : if this legend item refers to a hidden item
77858			// lineCap : cap style for line
77859			// lineDash
77860			// lineDashOffset :
77861			// lineJoin :
77862			// lineWidth :
77863			generateLabels: function(chart) {
77864				var data = chart.data;
77865				return helpers$1.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
77866					return {
77867						text: dataset.label,
77868						fillStyle: (!helpers$1.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]),
77869						hidden: !chart.isDatasetVisible(i),
77870						lineCap: dataset.borderCapStyle,
77871						lineDash: dataset.borderDash,
77872						lineDashOffset: dataset.borderDashOffset,
77873						lineJoin: dataset.borderJoinStyle,
77874						lineWidth: dataset.borderWidth,
77875						strokeStyle: dataset.borderColor,
77876						pointStyle: dataset.pointStyle,
77877
77878						// Below is extra data used for toggling the datasets
77879						datasetIndex: i
77880					};
77881				}, this) : [];
77882			}
77883		}
77884	},
77885
77886	legendCallback: function(chart) {
77887		var text = [];
77888		text.push('<ul class="' + chart.id + '-legend">');
77889		for (var i = 0; i < chart.data.datasets.length; i++) {
77890			text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
77891			if (chart.data.datasets[i].label) {
77892				text.push(chart.data.datasets[i].label);
77893			}
77894			text.push('</li>');
77895		}
77896		text.push('</ul>');
77897		return text.join('');
77898	}
77899});
77900
77901/**
77902 * Helper function to get the box width based on the usePointStyle option
77903 * @param {object} labelopts - the label options on the legend
77904 * @param {number} fontSize - the label font size
77905 * @return {number} width of the color box area
77906 */
77907function getBoxWidth(labelOpts, fontSize) {
77908	return labelOpts.usePointStyle && labelOpts.boxWidth > fontSize ?
77909		fontSize :
77910		labelOpts.boxWidth;
77911}
77912
77913/**
77914 * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required!
77915 */
77916var Legend = core_element.extend({
77917
77918	initialize: function(config) {
77919		helpers$1.extend(this, config);
77920
77921		// Contains hit boxes for each dataset (in dataset order)
77922		this.legendHitBoxes = [];
77923
77924		/**
77925 		 * @private
77926 		 */
77927		this._hoveredItem = null;
77928
77929		// Are we in doughnut mode which has a different data type
77930		this.doughnutMode = false;
vendor: 20,223 bytes, lines 77931-78737
77931	},
77932
77933	// These methods are ordered by lifecycle. Utilities then follow.
77934	// Any function defined here is inherited by all legend types.
77935	// Any function can be extended by the legend type
77936
77937	beforeUpdate: noop$1,
77938	update: function(maxWidth, maxHeight, margins) {
77939		var me = this;
77940
77941		// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
77942		me.beforeUpdate();
77943
77944		// Absorb the master measurements
77945		me.maxWidth = maxWidth;
77946		me.maxHeight = maxHeight;
77947		me.margins = margins;
77948
77949		// Dimensions
77950		me.beforeSetDimensions();
77951		me.setDimensions();
77952		me.afterSetDimensions();
77953		// Labels
77954		me.beforeBuildLabels();
77955		me.buildLabels();
77956		me.afterBuildLabels();
77957
77958		// Fit
77959		me.beforeFit();
77960		me.fit();
77961		me.afterFit();
77962		//
77963		me.afterUpdate();
77964
77965		return me.minSize;
77966	},
77967	afterUpdate: noop$1,
77968
77969	//
77970
77971	beforeSetDimensions: noop$1,
77972	setDimensions: function() {
77973		var me = this;
77974		// Set the unconstrained dimension before label rotation
77975		if (me.isHorizontal()) {
77976			// Reset position before calculating rotation
77977			me.width = me.maxWidth;
77978			me.left = 0;
77979			me.right = me.width;
77980		} else {
77981			me.height = me.maxHeight;
77982
77983			// Reset position before calculating rotation
77984			me.top = 0;
77985			me.bottom = me.height;
77986		}
77987
77988		// Reset padding
77989		me.paddingLeft = 0;
77990		me.paddingTop = 0;
77991		me.paddingRight = 0;
77992		me.paddingBottom = 0;
77993
77994		// Reset minSize
77995		me.minSize = {
77996			width: 0,
77997			height: 0
77998		};
77999	},
78000	afterSetDimensions: noop$1,
78001
78002	//
78003
78004	beforeBuildLabels: noop$1,
78005	buildLabels: function() {
78006		var me = this;
78007		var labelOpts = me.options.labels || {};
78008		var legendItems = helpers$1.callback(labelOpts.generateLabels, [me.chart], me) || [];
78009
78010		if (labelOpts.filter) {
78011			legendItems = legendItems.filter(function(item) {
78012				return labelOpts.filter(item, me.chart.data);
78013			});
78014		}
78015
78016		if (me.options.reverse) {
78017			legendItems.reverse();
78018		}
78019
78020		me.legendItems = legendItems;
78021	},
78022	afterBuildLabels: noop$1,
78023
78024	//
78025
78026	beforeFit: noop$1,
78027	fit: function() {
78028		var me = this;
78029		var opts = me.options;
78030		var labelOpts = opts.labels;
78031		var display = opts.display;
78032
78033		var ctx = me.ctx;
78034
78035		var labelFont = helpers$1.options._parseFont(labelOpts);
78036		var fontSize = labelFont.size;
78037
78038		// Reset hit boxes
78039		var hitboxes = me.legendHitBoxes = [];
78040
78041		var minSize = me.minSize;
78042		var isHorizontal = me.isHorizontal();
78043
78044		if (isHorizontal) {
78045			minSize.width = me.maxWidth; // fill all the width
78046			minSize.height = display ? 10 : 0;
78047		} else {
78048			minSize.width = display ? 10 : 0;
78049			minSize.height = me.maxHeight; // fill all the height
78050		}
78051
78052		// Increase sizes here
78053		if (display) {
78054			ctx.font = labelFont.string;
78055
78056			if (isHorizontal) {
78057				// Labels
78058
78059				// Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
78060				var lineWidths = me.lineWidths = [0];
78061				var totalHeight = 0;
78062
78063				ctx.textAlign = 'left';
78064				ctx.textBaseline = 'top';
78065
78066				helpers$1.each(me.legendItems, function(legendItem, i) {
78067					var boxWidth = getBoxWidth(labelOpts, fontSize);
78068					var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
78069
78070					if (i === 0 || lineWidths[lineWidths.length - 1] + width + labelOpts.padding > minSize.width) {
78071						totalHeight += fontSize + labelOpts.padding;
78072						lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = labelOpts.padding;
78073					}
78074
78075					// Store the hitbox width and height here. Final position will be updated in `draw`
78076					hitboxes[i] = {
78077						left: 0,
78078						top: 0,
78079						width: width,
78080						height: fontSize
78081					};
78082
78083					lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
78084				});
78085
78086				minSize.height += totalHeight;
78087
78088			} else {
78089				var vPadding = labelOpts.padding;
78090				var columnWidths = me.columnWidths = [];
78091				var totalWidth = labelOpts.padding;
78092				var currentColWidth = 0;
78093				var currentColHeight = 0;
78094				var itemHeight = fontSize + vPadding;
78095
78096				helpers$1.each(me.legendItems, function(legendItem, i) {
78097					var boxWidth = getBoxWidth(labelOpts, fontSize);
78098					var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
78099
78100					// If too tall, go to new column
78101					if (i > 0 && currentColHeight + itemHeight > minSize.height - vPadding) {
78102						totalWidth += currentColWidth + labelOpts.padding;
78103						columnWidths.push(currentColWidth); // previous column width
78104
78105						currentColWidth = 0;
78106						currentColHeight = 0;
78107					}
78108
78109					// Get max width
78110					currentColWidth = Math.max(currentColWidth, itemWidth);
78111					currentColHeight += itemHeight;
78112
78113					// Store the hitbox width and height here. Final position will be updated in `draw`
78114					hitboxes[i] = {
78115						left: 0,
78116						top: 0,
78117						width: itemWidth,
78118						height: fontSize
78119					};
78120				});
78121
78122				totalWidth += currentColWidth;
78123				columnWidths.push(currentColWidth);
78124				minSize.width += totalWidth;
78125			}
78126		}
78127
78128		me.width = minSize.width;
78129		me.height = minSize.height;
78130	},
78131	afterFit: noop$1,
78132
78133	// Shared Methods
78134	isHorizontal: function() {
78135		return this.options.position === 'top' || this.options.position === 'bottom';
78136	},
78137
78138	// Actually draw the legend on the canvas
78139	draw: function() {
78140		var me = this;
78141		var opts = me.options;
78142		var labelOpts = opts.labels;
78143		var globalDefaults = core_defaults.global;
78144		var defaultColor = globalDefaults.defaultColor;
78145		var lineDefault = globalDefaults.elements.line;
78146		var legendWidth = me.width;
78147		var lineWidths = me.lineWidths;
78148
78149		if (opts.display) {
78150			var ctx = me.ctx;
78151			var fontColor = valueOrDefault$d(labelOpts.fontColor, globalDefaults.defaultFontColor);
78152			var labelFont = helpers$1.options._parseFont(labelOpts);
78153			var fontSize = labelFont.size;
78154			var cursor;
78155
78156			// Canvas setup
78157			ctx.textAlign = 'left';
78158			ctx.textBaseline = 'middle';
78159			ctx.lineWidth = 0.5;
78160			ctx.strokeStyle = fontColor; // for strikethrough effect
78161			ctx.fillStyle = fontColor; // render in correct colour
78162			ctx.font = labelFont.string;
78163
78164			var boxWidth = getBoxWidth(labelOpts, fontSize);
78165			var hitboxes = me.legendHitBoxes;
78166
78167			// current position
78168			var drawLegendBox = function(x, y, legendItem) {
78169				if (isNaN(boxWidth) || boxWidth <= 0) {
78170					return;
78171				}
78172
78173				// Set the ctx for the box
78174				ctx.save();
78175
78176				var lineWidth = valueOrDefault$d(legendItem.lineWidth, lineDefault.borderWidth);
78177				ctx.fillStyle = valueOrDefault$d(legendItem.fillStyle, defaultColor);
78178				ctx.lineCap = valueOrDefault$d(legendItem.lineCap, lineDefault.borderCapStyle);
78179				ctx.lineDashOffset = valueOrDefault$d(legendItem.lineDashOffset, lineDefault.borderDashOffset);
78180				ctx.lineJoin = valueOrDefault$d(legendItem.lineJoin, lineDefault.borderJoinStyle);
78181				ctx.lineWidth = lineWidth;
78182				ctx.strokeStyle = valueOrDefault$d(legendItem.strokeStyle, defaultColor);
78183
78184				if (ctx.setLineDash) {
78185					// IE 9 and 10 do not support line dash
78186					ctx.setLineDash(valueOrDefault$d(legendItem.lineDash, lineDefault.borderDash));
78187				}
78188
78189				if (opts.labels && opts.labels.usePointStyle) {
78190					// Recalculate x and y for drawPoint() because its expecting
78191					// x and y to be center of figure (instead of top left)
78192					var radius = boxWidth * Math.SQRT2 / 2;
78193					var centerX = x + boxWidth / 2;
78194					var centerY = y + fontSize / 2;
78195
78196					// Draw pointStyle as legend symbol
78197					helpers$1.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY);
78198				} else {
78199					// Draw box as legend symbol
78200					if (lineWidth !== 0) {
78201						ctx.strokeRect(x, y, boxWidth, fontSize);
78202					}
78203					ctx.fillRect(x, y, boxWidth, fontSize);
78204				}
78205
78206				ctx.restore();
78207			};
78208			var fillText = function(x, y, legendItem, textWidth) {
78209				var halfFontSize = fontSize / 2;
78210				var xLeft = boxWidth + halfFontSize + x;
78211				var yMiddle = y + halfFontSize;
78212
78213				ctx.fillText(legendItem.text, xLeft, yMiddle);
78214
78215				if (legendItem.hidden) {
78216					// Strikethrough the text if hidden
78217					ctx.beginPath();
78218					ctx.lineWidth = 2;
78219					ctx.moveTo(xLeft, yMiddle);
78220					ctx.lineTo(xLeft + textWidth, yMiddle);
78221					ctx.stroke();
78222				}
78223			};
78224
78225			// Horizontal
78226			var isHorizontal = me.isHorizontal();
78227			if (isHorizontal) {
78228				cursor = {
78229					x: me.left + ((legendWidth - lineWidths[0]) / 2) + labelOpts.padding,
78230					y: me.top + labelOpts.padding,
78231					line: 0
78232				};
78233			} else {
78234				cursor = {
78235					x: me.left + labelOpts.padding,
78236					y: me.top + labelOpts.padding,
78237					line: 0
78238				};
78239			}
78240
78241			var itemHeight = fontSize + labelOpts.padding;
78242			helpers$1.each(me.legendItems, function(legendItem, i) {
78243				var textWidth = ctx.measureText(legendItem.text).width;
78244				var width = boxWidth + (fontSize / 2) + textWidth;
78245				var x = cursor.x;
78246				var y = cursor.y;
78247
78248				// Use (me.left + me.minSize.width) and (me.top + me.minSize.height)
78249				// instead of me.right and me.bottom because me.width and me.height
78250				// may have been changed since me.minSize was calculated
78251				if (isHorizontal) {
78252					if (i > 0 && x + width + labelOpts.padding > me.left + me.minSize.width) {
78253						y = cursor.y += itemHeight;
78254						cursor.line++;
78255						x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2) + labelOpts.padding;
78256					}
78257				} else if (i > 0 && y + itemHeight > me.top + me.minSize.height) {
78258					x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding;
78259					y = cursor.y = me.top + labelOpts.padding;
78260					cursor.line++;
78261				}
78262
78263				drawLegendBox(x, y, legendItem);
78264
78265				hitboxes[i].left = x;
78266				hitboxes[i].top = y;
78267
78268				// Fill the actual label
78269				fillText(x, y, legendItem, textWidth);
78270
78271				if (isHorizontal) {
78272					cursor.x += width + labelOpts.padding;
78273				} else {
78274					cursor.y += itemHeight;
78275				}
78276
78277			});
78278		}
78279	},
78280
78281	/**
78282	 * @private
78283	 */
78284	_getLegendItemAt: function(x, y) {
78285		var me = this;
78286		var i, hitBox, lh;
78287
78288		if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
78289			// See if we are touching one of the dataset boxes
78290			lh = me.legendHitBoxes;
78291			for (i = 0; i < lh.length; ++i) {
78292				hitBox = lh[i];
78293
78294				if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
78295					// Touching an element
78296					return me.legendItems[i];
78297				}
78298			}
78299		}
78300
78301		return null;
78302	},
78303
78304	/**
78305	 * Handle an event
78306	 * @private
78307	 * @param {IEvent} event - The event to handle
78308	 */
78309	handleEvent: function(e) {
78310		var me = this;
78311		var opts = me.options;
78312		var type = e.type === 'mouseup' ? 'click' : e.type;
78313		var hoveredItem;
78314
78315		if (type === 'mousemove') {
78316			if (!opts.onHover && !opts.onLeave) {
78317				return;
78318			}
78319		} else if (type === 'click') {
78320			if (!opts.onClick) {
78321				return;
78322			}
78323		} else {
78324			return;
78325		}
78326
78327		// Chart event already has relative position in it
78328		hoveredItem = me._getLegendItemAt(e.x, e.y);
78329
78330		if (type === 'click') {
78331			if (hoveredItem && opts.onClick) {
78332				// use e.native for backwards compatibility
78333				opts.onClick.call(me, e.native, hoveredItem);
78334			}
78335		} else {
78336			if (opts.onLeave && hoveredItem !== me._hoveredItem) {
78337				if (me._hoveredItem) {
78338					opts.onLeave.call(me, e.native, me._hoveredItem);
78339				}
78340				me._hoveredItem = hoveredItem;
78341			}
78342
78343			if (opts.onHover && hoveredItem) {
78344				// use e.native for backwards compatibility
78345				opts.onHover.call(me, e.native, hoveredItem);
78346			}
78347		}
78348	}
78349});
78350
78351function createNewLegendAndAttach(chart, legendOpts) {
78352	var legend = new Legend({
78353		ctx: chart.ctx,
78354		options: legendOpts,
78355		chart: chart
78356	});
78357
78358	core_layouts.configure(chart, legend, legendOpts);
78359	core_layouts.addBox(chart, legend);
78360	chart.legend = legend;
78361}
78362
78363var plugin_legend = {
78364	id: 'legend',
78365
78366	/**
78367	 * Backward compatibility: since 2.1.5, the legend is registered as a plugin, making
78368	 * Chart.Legend obsolete. To avoid a breaking change, we export the Legend as part of
78369	 * the plugin, which one will be re-exposed in the chart.js file.
78370	 * https://github.com/chartjs/Chart.js/pull/2640
78371	 * @private
78372	 */
78373	_element: Legend,
78374
78375	beforeInit: function(chart) {
78376		var legendOpts = chart.options.legend;
78377
78378		if (legendOpts) {
78379			createNewLegendAndAttach(chart, legendOpts);
78380		}
78381	},
78382
78383	beforeUpdate: function(chart) {
78384		var legendOpts = chart.options.legend;
78385		var legend = chart.legend;
78386
78387		if (legendOpts) {
78388			helpers$1.mergeIf(legendOpts, core_defaults.global.legend);
78389
78390			if (legend) {
78391				core_layouts.configure(chart, legend, legendOpts);
78392				legend.options = legendOpts;
78393			} else {
78394				createNewLegendAndAttach(chart, legendOpts);
78395			}
78396		} else if (legend) {
78397			core_layouts.removeBox(chart, legend);
78398			delete chart.legend;
78399		}
78400	},
78401
78402	afterEvent: function(chart, e) {
78403		var legend = chart.legend;
78404		if (legend) {
78405			legend.handleEvent(e);
78406		}
78407	}
78408};
78409
78410var noop$2 = helpers$1.noop;
78411
78412core_defaults._set('global', {
78413	title: {
78414		display: false,
78415		fontStyle: 'bold',
78416		fullWidth: true,
78417		padding: 10,
78418		position: 'top',
78419		text: '',
78420		weight: 2000         // by default greater than legend (1000) to be above
78421	}
78422});
78423
78424/**
78425 * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required!
78426 */
78427var Title = core_element.extend({
78428	initialize: function(config) {
78429		var me = this;
78430		helpers$1.extend(me, config);
78431
78432		// Contains hit boxes for each dataset (in dataset order)
78433		me.legendHitBoxes = [];
78434	},
78435
78436	// These methods are ordered by lifecycle. Utilities then follow.
78437
78438	beforeUpdate: noop$2,
78439	update: function(maxWidth, maxHeight, margins) {
78440		var me = this;
78441
78442		// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
78443		me.beforeUpdate();
78444
78445		// Absorb the master measurements
78446		me.maxWidth = maxWidth;
78447		me.maxHeight = maxHeight;
78448		me.margins = margins;
78449
78450		// Dimensions
78451		me.beforeSetDimensions();
78452		me.setDimensions();
78453		me.afterSetDimensions();
78454		// Labels
78455		me.beforeBuildLabels();
78456		me.buildLabels();
78457		me.afterBuildLabels();
78458
78459		// Fit
78460		me.beforeFit();
78461		me.fit();
78462		me.afterFit();
78463		//
78464		me.afterUpdate();
78465
78466		return me.minSize;
78467
78468	},
78469	afterUpdate: noop$2,
78470
78471	//
78472
78473	beforeSetDimensions: noop$2,
78474	setDimensions: function() {
78475		var me = this;
78476		// Set the unconstrained dimension before label rotation
78477		if (me.isHorizontal()) {
78478			// Reset position before calculating rotation
78479			me.width = me.maxWidth;
78480			me.left = 0;
78481			me.right = me.width;
78482		} else {
78483			me.height = me.maxHeight;
78484
78485			// Reset position before calculating rotation
78486			me.top = 0;
78487			me.bottom = me.height;
78488		}
78489
78490		// Reset padding
78491		me.paddingLeft = 0;
78492		me.paddingTop = 0;
78493		me.paddingRight = 0;
78494		me.paddingBottom = 0;
78495
78496		// Reset minSize
78497		me.minSize = {
78498			width: 0,
78499			height: 0
78500		};
78501	},
78502	afterSetDimensions: noop$2,
78503
78504	//
78505
78506	beforeBuildLabels: noop$2,
78507	buildLabels: noop$2,
78508	afterBuildLabels: noop$2,
78509
78510	//
78511
78512	beforeFit: noop$2,
78513	fit: function() {
78514		var me = this;
78515		var opts = me.options;
78516		var display = opts.display;
78517		var minSize = me.minSize;
78518		var lineCount = helpers$1.isArray(opts.text) ? opts.text.length : 1;
78519		var fontOpts = helpers$1.options._parseFont(opts);
78520		var textSize = display ? (lineCount * fontOpts.lineHeight) + (opts.padding * 2) : 0;
78521
78522		if (me.isHorizontal()) {
78523			minSize.width = me.maxWidth; // fill all the width
78524			minSize.height = textSize;
78525		} else {
78526			minSize.width = textSize;
78527			minSize.height = me.maxHeight; // fill all the height
78528		}
78529
78530		me.width = minSize.width;
78531		me.height = minSize.height;
78532
78533	},
78534	afterFit: noop$2,
78535
78536	// Shared Methods
78537	isHorizontal: function() {
78538		var pos = this.options.position;
78539		return pos === 'top' || pos === 'bottom';
78540	},
78541
78542	// Actually draw the title block on the canvas
78543	draw: function() {
78544		var me = this;
78545		var ctx = me.ctx;
78546		var opts = me.options;
78547
78548		if (opts.display) {
78549			var fontOpts = helpers$1.options._parseFont(opts);
78550			var lineHeight = fontOpts.lineHeight;
78551			var offset = lineHeight / 2 + opts.padding;
78552			var rotation = 0;
78553			var top = me.top;
78554			var left = me.left;
78555			var bottom = me.bottom;
78556			var right = me.right;
78557			var maxWidth, titleX, titleY;
78558
78559			ctx.fillStyle = helpers$1.valueOrDefault(opts.fontColor, core_defaults.global.defaultFontColor); // render in correct colour
78560			ctx.font = fontOpts.string;
78561
78562			// Horizontal
78563			if (me.isHorizontal()) {
78564				titleX = left + ((right - left) / 2); // midpoint of the width
78565				titleY = top + offset;
78566				maxWidth = right - left;
78567			} else {
78568				titleX = opts.position === 'left' ? left + offset : right - offset;
78569				titleY = top + ((bottom - top) / 2);
78570				maxWidth = bottom - top;
78571				rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
78572			}
78573
78574			ctx.save();
78575			ctx.translate(titleX, titleY);
78576			ctx.rotate(rotation);
78577			ctx.textAlign = 'center';
78578			ctx.textBaseline = 'middle';
78579
78580			var text = opts.text;
78581			if (helpers$1.isArray(text)) {
78582				var y = 0;
78583				for (var i = 0; i < text.length; ++i) {
78584					ctx.fillText(text[i], 0, y, maxWidth);
78585					y += lineHeight;
78586				}
78587			} else {
78588				ctx.fillText(text, 0, 0, maxWidth);
78589			}
78590
78591			ctx.restore();
78592		}
78593	}
78594});
78595
78596function createNewTitleBlockAndAttach(chart, titleOpts) {
78597	var title = new Title({
78598		ctx: chart.ctx,
78599		options: titleOpts,
78600		chart: chart
78601	});
78602
78603	core_layouts.configure(chart, title, titleOpts);
78604	core_layouts.addBox(chart, title);
78605	chart.titleBlock = title;
78606}
78607
78608var plugin_title = {
78609	id: 'title',
78610
78611	/**
78612	 * Backward compatibility: since 2.1.5, the title is registered as a plugin, making
78613	 * Chart.Title obsolete. To avoid a breaking change, we export the Title as part of
78614	 * the plugin, which one will be re-exposed in the chart.js file.
78615	 * https://github.com/chartjs/Chart.js/pull/2640
78616	 * @private
78617	 */
78618	_element: Title,
78619
78620	beforeInit: function(chart) {
78621		var titleOpts = chart.options.title;
78622
78623		if (titleOpts) {
78624			createNewTitleBlockAndAttach(chart, titleOpts);
78625		}
78626	},
78627
78628	beforeUpdate: function(chart) {
78629		var titleOpts = chart.options.title;
78630		var titleBlock = chart.titleBlock;
78631
78632		if (titleOpts) {
78633			helpers$1.mergeIf(titleOpts, core_defaults.global.title);
78634
78635			if (titleBlock) {
78636				core_layouts.configure(chart, titleBlock, titleOpts);
78637				titleBlock.options = titleOpts;
78638			} else {
78639				createNewTitleBlockAndAttach(chart, titleOpts);
78640			}
78641		} else if (titleBlock) {
78642			core_layouts.removeBox(chart, titleBlock);
78643			delete chart.titleBlock;
78644		}
78645	}
78646};
78647
78648var plugins = {};
78649var filler = plugin_filler;
78650var legend = plugin_legend;
78651var title = plugin_title;
78652plugins.filler = filler;
78653plugins.legend = legend;
78654plugins.title = title;
78655
78656/**
78657 * @namespace Chart
78658 */
78659
78660
78661core_controller.helpers = helpers$1;
78662
78663// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests!
78664core_helpers(core_controller);
78665
78666core_controller._adapters = core_adapters;
78667core_controller.Animation = core_animation;
78668core_controller.animationService = core_animations;
78669core_controller.controllers = controllers;
78670core_controller.DatasetController = core_datasetController;
78671core_controller.defaults = core_defaults;
78672core_controller.Element = core_element;
78673core_controller.elements = elements;
78674core_controller.Interaction = core_interaction;
78675core_controller.layouts = core_layouts;
78676core_controller.platform = platform;
78677core_controller.plugins = core_plugins;
78678core_controller.Scale = core_scale;
78679core_controller.scaleService = core_scaleService;
78680core_controller.Ticks = core_ticks;
78681core_controller.Tooltip = core_tooltip;
78682
78683// Register built-in scales
78684
78685core_controller.helpers.each(scales, function(scale, type) {
78686	core_controller.scaleService.registerScaleType(type, scale, scale._defaults);
78687});
78688
78689// Load to register built-in adapters (as side effects)
78690
78691
78692// Loading built-in plugins
78693
78694for (var k in plugins) {
78695	if (plugins.hasOwnProperty(k)) {
78696		core_controller.plugins.register(plugins[k]);
78697	}
78698}
78699
78700core_controller.platform.initialize();
78701
78702var src = core_controller;
78703if (typeof window !== 'undefined') {
78704	window.Chart = core_controller;
78705}
78706
78707// DEPRECATIONS
78708
78709/**
78710 * Provided for backward compatibility, not available anymore
78711 * @namespace Chart.Chart
78712 * @deprecated since version 2.8.0
78713 * @todo remove at version 3
78714 * @private
78715 */
78716core_controller.Chart = core_controller;
78717
78718/**
78719 * Provided for backward compatibility, not available anymore
78720 * @namespace Chart.Legend
78721 * @deprecated since version 2.1.5
78722 * @todo remove at version 3
78723 * @private
78724 */
78725core_controller.Legend = plugins.legend._element;
78726
78727/**
78728 * Provided for backward compatibility, not available anymore
78729 * @namespace Chart.Title
78730 * @deprecated since version 2.1.5
78731 * @todo remove at version 3
78732 * @private
78733 */
78734core_controller.Title = plugins.title._element;
78735
78736/**
78737 * Provided for backward compatibility, use Chart.plugins instead
78738 * @namespace Chart.pluginService
78739 * @deprecated since version 2.1.5
78740 * @todo remove at version 3
78741 * @private
78742 */
78743core_controller.pluginService = core_controller.plugins;
78744
78745/**
78746 * Provided for backward compatibility, inheriting from Chart.PlugingBase has no
78747 * effect, instead simply create/register plugins via plain JavaScript objects.
78748 * @interface Chart.PluginBase
78749 * @deprecated since version 2.5.0
78750 * @todo remove at version 3
78751 * @private
78752 */
78753core_controller.PluginBase = core_controller.Element.extend({});
78754
78755/**
78756 * Provided for backward compatibility, use Chart.helpers.canvas instead.
78757 * @namespace Chart.canvasHelpers
78758 * @deprecated since version 2.6.0
78759 * @todo remove at version 3
78760 * @private
78761 */
78762core_controller.canvasHelpers = core_controller.helpers.canvas;
78763
78764/**
78765 * Provided for backward compatibility, use Chart.layouts instead.
78766 * @namespace Chart.layoutService
78767 * @deprecated since version 2.7.3
78768 * @todo remove at version 3
78769 * @private
78770 */
78771core_controller.layoutService = core_controller.layouts;
78772
78773/**
78774 * Provided for backward compatibility, not available anymore.
78775 * @namespace Chart.LinearScaleBase
78776 * @deprecated since version 2.8
78777 * @todo remove at version 3
78778 * @private
78779 */
78780core_controller.LinearScaleBase = scale_linearbase;
78781
78782/**
78783 * Provided for backward compatibility, instead we should create a new Chart
78784 * by setting the type in the config (`new Chart(id, {type: '{chart-type}'}`).
78785 * @deprecated since version 2.8.0
78786 * @todo remove at version 3
78787 */
78788core_controller.helpers.each(
78789	[
78790		'Bar',
78791		'Bubble',
78792		'Doughnut',
78793		'Line',
78794		'PolarArea',
78795		'Radar',
78796		'Scatter'
78797	],
78798	function(klass) {
78799		core_controller[klass] = function(ctx, cfg) {
78800			return new core_controller(ctx, core_controller.helpers.merge(cfg || {}, {
78801				type: klass.charAt(0).toLowerCase() + klass.slice(1)
78802			}));
78803		};
78804	}
78805);
78806
78807return src;
78808
78809})));
78810
78811!function(a){"use strict";a.sessionTimeout=function(b){function c(){n||(a.ajax({type:i.ajaxType,url:i.keepAliveUrl,data:i.ajaxData}),n=!0,setTimeout(function(){n=!1},i.keepAliveInterval))}function d(){clearTimeout(g),(i.countdownMessage||i.countdownBar)&&f("session",!0),"function"==typeof i.onStart&&i.onStart(i),i.keepAlive&&c(),g=setTimeout(function(){"function"!=typeof i.onWarn?a("#session-timeout-dialog").modal("show"):i.onWarn(i),e()},i.warnAfter)}function e(){clearTimeout(g),a("#session-timeout-dialog").hasClass("in")||!i.countdownMessage&&!i.countdownBar||f("dialog",!0),g=setTimeout(function(){"function"!=typeof i.onRedir?window.location=i.redirUrl:i.onRedir(i)},i.redirAfter-i.warnAfter)}function f(b,c){clearTimeout(j.timer),"dialog"===b&&c?j.timeLeft=Math.floor((i.redirAfter-i.warnAfter)/1e3):"session"===b&&c&&(j.timeLeft=Math.floor(i.redirAfter/1e3)),i.countdownBar&&"dialog"===b?j.percentLeft=Math.floor(j.timeLeft/((i.redirAfter-i.warnAfter)/1e3)*100):i.countdownBar&&"session"===b&&(j.percentLeft=Math.floor(j.timeLeft/(i.redirAfter/1e3)*100));var d=a(".countdown-holder"),e=j.timeLeft>=0?j.timeLeft:0;if(i.countdownSmart){var g=Math.floor(e/60),h=e%60,k=g>0?g+"m":"";k.length>0&&(k+=" "),k+=h+"s",d.text(k)}else d.text(e+"s");i.countdownBar&&a(".countdown-bar").css("width",j.percentLeft+"%"),j.timeLeft=j.timeLeft-1,j.timer=setTimeout(function(){f(b)},1e3)}var g,h={title:"Your Session is About to Expire!",message:"Your session is about to expire.",logoutButton:"Logout",keepAliveButton:"Stay Connected",keepAliveUrl:"/keep-alive",ajaxType:"POST",ajaxData:"",redirUrl:"/timed-out",logoutUrl:"/log-out",warnAfter:9e5,redirAfter:12e5,keepAliveInterval:5e3,keepAlive:!0,ignoreUserActivity:!1,onStart:!1,onWarn:!1,onRedir:!1,countdownMessage:!1,countdownBar:!1,countdownSmart:!1},i=h,j={};if(b&&(i=a.extend(h,b)),i.warnAfter>=i.redirAfter)return console.error('Bootstrap-session-timeout plugin is miss-configured. Option "redirAfter" must be equal or greater than "warnAfter".'),!1;if("function"!=typeof i.onWarn){var k=i.countdownMessage?"<p>"+i.countdownMessage.replace(/{timer}/g,'<span class="countdown-holder"></span>')+"</p>":"",l=i.countdownBar?'<div class="progress">                   <div class="progress-bar progress-bar-striped countdown-bar active" role="progressbar" style="min-width: 15px; width: 100%;">
78811                     <span class="countdown-holder"></span>                   </div>                 </div>':"";a("body").append('<div class="modal fade" id="session-timeout-dialog">               <div class="modal-dialog">                 <div class="modal-content">                   <div class="modal-header">                     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>                     <h4 class="modal-title">'+i.title+'</h4>                   </div>                   <div class="modal-body">                     <p>'+i.message+"</p>                     "+k+"                     "+l+'                   </div>                   <div class="modal-footer">                     <button id="session-timeout-dialog-logout" type="button" class="btn btn-default">'+i.logoutButton+'</button>                     <button id="session-timeout-dialog-keepalive" type="button" class="btn btn-primary" data-dismiss="modal">'+i.keepAliveButton+"</button>                   </div>                 </div>               </div>              </div>"),a("#session-timeout-dialog-logout").on("click",function(){window.location=i.logoutUrl}),a("#session-timeout-dialog").on("hide.bs.modal",function(){d()})}if(!i.ignoreUserActivity){var m=[-1,-1];a(document).on("keyup mouseup mousemove touchend touchmove",function(b){if("mousemove"===b.type){if(b.clientX===m[0]&&b.clientY===m[1])return;m[0]=b.clientX,m[1]=b.clientY}d(),a("#session-timeout-dialog").length>0&&a("#session-timeout-dialog").data("bs.modal")&&a("#session-timeout-dialog").data("bs.modal").isShown&&(a("#session-timeout-dialog").modal("hide"),a("body").removeClass("modal-open"),a("div.modal-backdrop").remove())})}var n=!1;d()}}(jQuery);
78812/*! Idle Timer v1.1.0 2016-03-21 | https://github.com/thorst/jquery-idletimer | (c) 2016 Paul Irish | Licensed MIT */
78813!function(a){a.idleTimer=function(b,c){var d;"object"==typeof b?(d=b,b=null):"number"==typeof b&&(d={timeout:b},b=null),c=c||document,d=a.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},d);var e=a(c),f=e.data("idleTimerObj")||{},g=function(b){var d=a.data(c,"idleTimerObj")||{};d.idle=!d.idle,d.olddate=+new Date;var e=a.Event((d.idle?"idle":"active")+".idleTimer");a(c).trigger(e,[c,a.extend({},d),b])},h=function(b){var d=a.data(c,"idleTimerObj")||{};if(("storage"!==b.type||b.originalEvent.key===d.timerSyncId)&&null==d.remaining){if("mousemove"===b.type){if(b.pageX===d.pageX&&b.pageY===d.pageY)return;if("undefined"==typeof b.pageX&&"undefined"==typeof b.pageY)return;var e=+new Date-d.olddate;if(200>e)return}clearTimeout(d.tId),d.idle&&g(b),d.lastActive=+new Date,d.pageX=b.pageX,d.pageY=b.pageY,"storage"!==b.type&&d.timerSyncId&&"undefined"!=typeof localStorage&&localStorage.setItem(d.timerSyncId,d.lastActive),d.tId=setTimeout(g,d.timeout)}},i=function(){var b=a.data(c,"idleTimerObj")||{};b.idle=b.idleBackup,b.olddate=+new Date,b.lastActive=b.olddate,b.remaining=null,clearTimeout(b.tId),b.idle||(b.tId=setTimeout(g,b.timeout))},j=function(){var b=a.data(c,"idleTimerObj")||{};null==b.remaining&&(b.remaining=b.timeout-(+new Date-b.olddate),clearTimeout(b.tId))},k=function(){var b=a.data(c,"idleTimerObj")||{};null!=b.remaining&&(b.idle||(b.tId=setTimeout(g,b.remaining)),b.remaining=null)},l=function(){var b=a.data(c,"idleTimerObj")||{};clearTimeout(b.tId),e.removeData("idleTimerObj"),e.off("._idleTimer")},m=function(){var b=a.data(c,"idleTimerObj")||{};if(b.idle)return 0;if(null!=b.remaining)return b.remaining;var d=b.timeout-(+new Date-b.lastActive);return 0>d&&(d=0),d};if(null===b&&"undefined"!=typeof f.idle)return i(),e;if(null===b);else{if(null!==b&&"undefined"==typeof f.idle)return!1;if("destroy"===b)return l(),e;if("pause"===b)return j(),e;if("resume"===b)return k(),e;if("reset"===b)return i(),e;if("getRemainingTime"===b)return m();if("getElapsedTime"===b)return+new Date-f.olddate;if("getLastActiveTime"===b)return f.lastActive;if("isIdle"===b)return f.idle}return e.on(a.trim((d.events+" ").split(" ").join("._idleTimer ")),function(a){h(a)}),d.timerSyncId&&a(window).bind("storage",h),f=a.extend({},{olddate:+new Date,lastActive:+new Date,idle:d.idle,idleBackup:d.idle,timeout:d.timeout,remaining:null,timerSyncId:d.timerSyncId,tId:null,pageX:null,pageY:null}),f.idle||(f.tId=setTimeout(g,f.timeout)),a.data(c,"idleTimerObj",f),e},a.fn.idleTimer=function(b){return this[0]?a.idleTimer(b,this[0]):this}}(jQuery);
78814/*!
78815Waypoints - 4.0.1
78816Copyright © 2011-2016 Caleb Troughton
78817Licensed under the MIT license.
78818https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
78819*/
78820(function() {
78821  'use strict'
78822
78823  var keyCounter = 0
78824  var allWaypoints = {}
78825
78826  /* http://imakewebthings.com/waypoints/api/waypoint */
78827  function Waypoint(options) {
78828    if (!options) {
78829      throw new Error('No options passed to Waypoint constructor')
78830    }
78831    if (!options.element) {
78832      throw new Error('No element option passed to Waypoint constructor')
78833    }
78834    if (!options.handler) {
78835      throw new Error('No handler option passed to Waypoint constructor')
78836    }
78837
78838    this.key = 'waypoint-' + keyCounter
78839    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
78840    this.element = this.options.element
78841    this.adapter = new Waypoint.Adapter(this.element)
78842    this.callback = options.handler
78843    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
78844    this.enabled = this.options.enabled
78845    this.triggerPoint = null
78846    this.group = Waypoint.Group.findOrCreate({
78847      name: this.options.group,
78848      axis: this.axis
78849    })
78850    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
78851
78852    if (Waypoint.offsetAliases[this.options.offset]) {
78853      this.options.offset = Waypoint.offsetAliases[this.options.offset]
78854    }
78855    this.group.add(this)
78856    this.context.add(this)
78857    allWaypoints[this.key] = this
78858    keyCounter += 1
78859  }
78860
78861  /* Private */
78862  Waypoint.prototype.queueTrigger = function(direction) {
78863    this.group.queueTrigger(this, direction)
78864  }
78865
78866  /* Private */
78867  Waypoint.prototype.trigger = function(args) {
78868    if (!this.enabled) {
78869      return
78870    }
78871    if (this.callback) {
78872      this.callback.apply(this, args)
78873    }
78874  }
78875
78876  /* Public */
78877  /* http://imakewebthings.com/waypoints/api/destroy */
78878  Waypoint.prototype.destroy = function() {
78879    this.context.remove(this)
78880    this.group.remove(this)
78881    delete allWaypoints[this.key]
78882  }
78883
78884  /* Public */
78885  /* http://imakewebthings.com/waypoints/api/disable */
78886  Waypoint.prototype.disable = function() {
78887    this.enabled = false
78888    return this
78889  }
78890
78891  /* Public */
78892  /* http://imakewebthings.com/waypoints/api/enable */
78893  Waypoint.prototype.enable = function() {
78894    this.context.refresh()
78895    this.enabled = true
78896    return this
78897  }
78898
78899  /* Public */
78900  /* http://imakewebthings.com/waypoints/api/next */
78901  Waypoint.prototype.next = function() {
78902    return this.group.next(this)
78903  }
78904
78905  /* Public */
78906  /* http://imakewebthings.com/waypoints/api/previous */
78907  Waypoint.prototype.previous = function() {
78908    return this.group.previous(this)
78909  }
78910
78911  /* Private */
78912  Waypoint.invokeAll = function(method) {
78913    var allWaypointsArray = []
78914    for (var waypointKey in allWaypoints) {
78915      allWaypointsArray.push(allWaypoints[waypointKey])
78916    }
78917    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
78918      allWaypointsArray[i][method]()
78919    }
78920  }
78921
78922  /* Public */
78923  /* http://imakewebthings.com/waypoints/api/destroy-all */
78924  Waypoint.destroyAll = function() {
78925    Waypoint.invokeAll('destroy')
78926  }
78927
78928  /* Public */
78929  /* http://imakewebthings.com/waypoints/api/disable-all */
78930  Waypoint.disableAll = function() {
78931    Waypoint.invokeAll('disable')
78932  }
78933
78934  /* Public */
78935  /* http://imakewebthings.com/waypoints/api/enable-all */
78936  Waypoint.enableAll = function() {
78937    Waypoint.Context.refreshAll()
78938    for (var waypointKey in allWaypoints) {
78939      allWaypoints[waypointKey].enabled = true
78940    }
78941    return this
78942  }
78943
78944  /* Public */
78945  /* http://imakewebthings.com/waypoints/api/refresh-all */
78946  Waypoint.refreshAll = function() {
78947    Waypoint.Context.refreshAll()
78948  }
78949
78950  /* Public */
78951  /* http://imakewebthings.com/waypoints/api/viewport-height */
78952  Waypoint.viewportHeight = function() {
78953    return window.innerHeight || document.documentElement.clientHeight
78954  }
78955
78956  /* Public */
78957  /* http://imakewebthings.com/waypoints/api/viewport-width */
78958  Waypoint.viewportWidth = function() {
78959    return document.documentElement.clientWidth
78960  }
78961
78962  Waypoint.adapters = []
78963
78964  Waypoint.defaults = {
78965    context: window,
78966    continuous: true,
78967    enabled: true,
78968    group: 'default',
78969    horizontal: false,
78970    offset: 0
78971  }
78972
78973  Waypoint.offsetAliases = {
78974    'bottom-in-view': function() {
78975      return this.context.innerHeight() - this.adapter.outerHeight()
78976    },
78977    'right-in-view': function() {
78978      return this.context.innerWidth() - this.adapter.outerWidth()
78979    }
78980  }
78981
78982  window.Waypoint = Waypoint
78983}())
78984;(function() {
78985  'use strict'
78986
78987  function requestAnimationFrameShim(callback) {
78988    window.setTimeout(callback, 1000 / 60)
78989  }
78990
78991  var keyCounter = 0
78992  var contexts = {}
78993  var Waypoint = window.Waypoint
78994  var oldWindowLoad = window.onload
78995
78996  /* http://imakewebthings.com/waypoints/api/context */
78997  function Context(element) {
78998    this.element = element
78999    this.Adapter = Waypoint.Adapter
79000    this.adapter = new this.Adapter(element)
79001    this.key = 'waypoint-context-' + keyCounter
79002    this.didScroll = false
79003    this.didResize = false
79004    this.oldScroll = {
79005      x: this.adapter.scrollLeft(),
79006      y: this.adapter.scrollTop()
79007    }
79008    this.waypoints = {
79009      vertical: {},
79010      horizontal: {}
79011    }
79012
79013    element.waypointContextKey = this.key
79014    contexts[element.waypointContextKey] = this
79015    keyCounter += 1
79016    if (!Waypoint.windowContext) {
79017      Waypoint.windowContext = true
79018      Waypoint.windowContext = new Context(window)
79019    }
79020
79021    this.createThrottledScrollHandler()
79022    this.createThrottledResizeHandler()
79023  }
79024
79025  /* Private */
79026  Context.prototype.add = function(waypoint) {
79027    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
79028    this.waypoints[axis][waypoint.key] = waypoint
79029    this.refresh()
79030  }
79031
79032  /* Private */
79033  Context.prototype.checkEmpty = function() {
79034    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
79035    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
79036    var isWindow = this.element == this.element.window
79037    if (horizontalEmpty && verticalEmpty && !isWindow) {
79038      this.adapter.off('.waypoints')
79039      delete contexts[this.key]
79040    }
79041  }
79042
79043  /* Private */
79044  Context.prototype.createThrottledResizeHandler = function() {
79045    var self = this
79046
79047    function resizeHandler() {
79048      self.handleResize()
79049      self.didResize = false
79050    }
79051
79052    this.adapter.on('resize.waypoints', function() {
79053      if (!self.didResize) {
79054        self.didResize = true
79055        Waypoint.requestAnimationFrame(resizeHandler)
79056      }
79057    })
79058  }
79059
79060  /* Private */
79061  Context.prototype.createThrottledScrollHandler = function() {
79062    var self = this
79063    function scrollHandler() {
79064      self.handleScroll()
79065      self.didScroll = false
79066    }
79067
79068    this.adapter.on('scroll.waypoints', function() {
79069      if (!self.didScroll || Waypoint.isTouch) {
79070        self.didScroll = true
79071        Waypoint.requestAnimationFrame(scrollHandler)
79072      }
79073    })
79074  }
79075
79076  /* Private */
79077  Context.prototype.handleResize = function() {
79078    Waypoint.Context.refreshAll()
79079  }
79080
79081  /* Private */
79082  Context.prototype.handleScroll = function() {
79083    var triggeredGroups = {}
79084    var axes = {
79085      horizontal: {
79086        newScroll: this.adapter.scrollLeft(),
79087        oldScroll: this.oldScroll.x,
79088        forward: 'right',
79089        backward: 'left'
79090      },
79091      vertical: {
79092        newScroll: this.adapter.scrollTop(),
79093        oldScroll: this.oldScroll.y,
79094        forward: 'down',
79095        backward: 'up'
79096      }
79097    }
79098
79099    for (var axisKey in axes) {
79100      var axis = axes[axisKey]
79101      var isForward = axis.newScroll > axis.oldScroll
79102      var direction = isForward ? axis.forward : axis.backward
79103
79104      for (var waypointKey in this.waypoints[axisKey]) {
79105        var waypoint = this.waypoints[axisKey][waypointKey]
79106        if (waypoint.triggerPoint === null) {
79107          continue
79108        }
79109        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
79110        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
79111        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
79112        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
79113        if (crossedForward || crossedBackward) {
79114          waypoint.queueTrigger(direction)
79115          triggeredGroups[waypoint.group.id] = waypoint.group
79116        }
79117      }
79118    }
79119
79120    for (var groupKey in triggeredGroups) {
79121      triggeredGroups[groupKey].flushTriggers()
79122    }
79123
79124    this.oldScroll = {
79125      x: axes.horizontal.newScroll,
79126      y: axes.vertical.newScroll
79127    }
79128  }
79129
79130  /* Private */
79131  Context.prototype.innerHeight = function() {
79132    /*eslint-disable eqeqeq */
79133    if (this.element == this.element.window) {
79134      return Waypoint.viewportHeight()
79135    }
79136    /*eslint-enable eqeqeq */
79137    return this.adapter.innerHeight()
79138  }
79139
79140  /* Private */
79141  Context.prototype.remove = function(waypoint) {
79142    delete this.waypoints[waypoint.axis][waypoint.key]
79143    this.checkEmpty()
79144  }
79145
79146  /* Private */
79147  Context.prototype.innerWidth = function() {
79148    /*eslint-disable eqeqeq */
79149    if (this.element == this.element.window) {
79150      return Waypoint.viewportWidth()
79151    }
79152    /*eslint-enable eqeqeq */
79153    return this.adapter.innerWidth()
79154  }
79155
79156  /* Public */
79157  /* http://imakewebthings.com/waypoints/api/context-destroy */
79158  Context.prototype.destroy = function() {
79159    var allWaypoints = []
79160    for (var axis in this.waypoints) {
79161      for (var waypointKey in this.waypoints[axis]) {
79162        allWaypoints.push(this.waypoints[axis][waypointKey])
79163      }
79164    }
79165    for (var i = 0, end = allWaypoints.length; i < end; i++) {
79166      allWaypoints[i].destroy()
79167    }
79168  }
79169
79170  /* Public */
79171  /* http://imakewebthings.com/waypoints/api/context-refresh */
79172  Context.prototype.refresh = function() {
79173    /*eslint-disable eqeqeq */
79174    var isWindow = this.element == this.element.window
79175    /*eslint-enable eqeqeq */
79176    var contextOffset = isWindow ? undefined : this.adapter.offset()
79177    var triggeredGroups = {}
79178    var axes
79179
79180    this.handleScroll()
79181    axes = {
79182      horizontal: {
79183        contextOffset: isWindow ? 0 : contextOffset.left,
79184        contextScroll: isWindow ? 0 : this.oldScroll.x,
79185        contextDimension: this.innerWidth(),
79186        oldScroll: this.oldScroll.x,
79187        forward: 'right',
79188        backward: 'left',
79189        offsetProp: 'left'
79190      },
79191      vertical: {
79192        contextOffset: isWindow ? 0 : contextOffset.top,
79193        contextScroll: isWindow ? 0 : this.oldScroll.y,
79194        contextDimension: this.innerHeight(),
79195        oldScroll: this.oldScroll.y,
79196        forward: 'down',
79197        backward: 'up',
79198        offsetProp: 'top'
79199      }
79200    }
79201
79202    for (var axisKey in axes) {
79203      var axis = axes[axisKey]
79204      for (var waypointKey in this.waypoints[axisKey]) {
79205        var waypoint = this.waypoints[axisKey][waypointKey]
79206        var adjustment = waypoint.options.offset
79207        var oldTriggerPoint = waypoint.triggerPoint
79208        var elementOffset = 0
79209        var freshWaypoint = oldTriggerPoint == null
79210        var contextModifier, wasBeforeScroll, nowAfterScroll
79211        var triggeredBackward, triggeredForward
79212
79213        if (waypoint.element !== waypoint.element.window) {
79214          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
79215        }
79216
79217        if (typeof adjustment === 'function') {
79218          adjustment = adjustment.apply(waypoint)
79219        }
79220        else if (typeof adjustment === 'string') {
79221          adjustment = parseFloat(adjustment)
79222          if (waypoint.options.offset.indexOf('%') > - 1) {
79223            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
79224          }
79225        }
79226
79227        contextModifier = axis.contextScroll - axis.contextOffset
79228        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
79229        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
79230        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
79231        triggeredBackward = wasBeforeScroll && nowAfterScroll
79232        triggeredForward = !wasBeforeScroll && !nowAfterScroll
79233
79234        if (!freshWaypoint && triggeredBackward) {
79235          waypoint.queueTrigger(axis.backward)
79236          triggeredGroups[waypoint.group.id] = waypoint.group
79237        }
79238        else if (!freshWaypoint && triggeredForward) {
79239          waypoint.queueTrigger(axis.forward)
79240          triggeredGroups[waypoint.group.id] = waypoint.group
79241        }
79242        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
79243          waypoint.queueTrigger(axis.forward)
79244          triggeredGroups[waypoint.group.id] = waypoint.group
79245        }
79246      }
79247    }
79248
79249    Waypoint.requestAnimationFrame(function() {
79250      for (var groupKey in triggeredGroups) {
79251        triggeredGroups[groupKey].flushTriggers()
79252      }
79253    })
79254
79255    return this
79256  }
79257
79258  /* Private */
79259  Context.findOrCreateByElement = function(element) {
79260    return Context.findByElement(element) || new Context(element)
79261  }
79262
79263  /* Private */
79264  Context.refreshAll = function() {
79265    for (var contextId in contexts) {
79266      contexts[contextId].refresh()
79267    }
79268  }
79269
79270  /* Public */
79271  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
79272  Context.findByElement = function(element) {
79273    return contexts[element.waypointContextKey]
79274  }
79275
79276  window.onload = function() {
79277    if (oldWindowLoad) {
79278      oldWindowLoad()
79279    }
79280    Context.refreshAll()
79281  }
79282
79283
79284  Waypoint.requestAnimationFrame = function(callback) {
79285    var requestFn = window.requestAnimationFrame ||
79286      window.mozRequestAnimationFrame ||
79287      window.webkitRequestAnimationFrame ||
79288      requestAnimationFrameShim
79289    requestFn.call(window, callback)
79290  }
79291  Waypoint.Context = Context
79292}())
79293;(function() {
79294  'use strict'
79295
79296  function byTriggerPoint(a, b) {
79297    return a.triggerPoint - b.triggerPoint
79298  }
79299
79300  function byReverseTriggerPoint(a, b) {
79301    return b.triggerPoint - a.triggerPoint
79302  }
79303
79304  var groups = {
79305    vertical: {},
79306    horizontal: {}
79307  }
79308  var Waypoint = window.Waypoint
79309
79310  /* http://imakewebthings.com/waypoints/api/group */
79311  function Group(options) {
79312    this.name = options.name
79313    this.axis = options.axis
79314    this.id = this.name + '-' + this.axis
79315    this.waypoints = []
79316    this.clearTriggerQueues()
79317    groups[this.axis][this.name] = this
79318  }
79319
79320  /* Private */
79321  Group.prototype.add = function(waypoint) {
79322    this.waypoints.push(waypoint)
79323  }
79324
79325  /* Private */
79326  Group.prototype.clearTriggerQueues = function() {
79327    this.triggerQueues = {
79328      up: [],
79329      down: [],
79330      left: [],
79331      right: []
79332    }
79333  }
79334
79335  /* Private */
79336  Group.prototype.flushTriggers = function() {
79337    for (var direction in this.triggerQueues) {
79338      var waypoints = this.triggerQueues[direction]
79339      var reverse = direction === 'up' || direction === 'left'
79340      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
79341      for (var i = 0, end = waypoints.length; i < end; i += 1) {
79342        var waypoint = waypoints[i]
79343        if (waypoint.options.continuous || i === waypoints.length - 1) {
79344          waypoint.trigger([direction])
79345        }
79346      }
79347    }
79348    this.clearTriggerQueues()
79349  }
79350
79351  /* Private */
79352  Group.prototype.next = function(waypoint) {
79353    this.waypoints.sort(byTriggerPoint)
79354    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
79355    var isLast = index === this.waypoints.length - 1
79356    return isLast ? null : this.waypoints[index + 1]
79357  }
79358
79359  /* Private */
79360  Group.prototype.previous = function(waypoint) {
79361    this.waypoints.sort(byTriggerPoint)
79362    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
79363    return index ? this.waypoints[index - 1] : null
79364  }
79365
79366  /* Private */
79367  Group.prototype.queueTrigger = function(waypoint, direction) {
79368    this.triggerQueues[direction].push(waypoint)
79369  }
79370
79371  /* Private */
79372  Group.prototype.remove = function(waypoint) {
79373    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
79374    if (index > -1) {
79375      this.waypoints.splice(index, 1)
79376    }
79377  }
79378
79379  /* Public */
79380  /* http://imakewebthings.com/waypoints/api/first */
79381  Group.prototype.first = function() {
79382    return this.waypoints[0]
79383  }
79384
79385  /* Public */
79386  /* http://imakewebthings.com/waypoints/api/last */
79387  Group.prototype.last = function() {
79388    return this.waypoints[this.waypoints.length - 1]
79389  }
79390
79391  /* Private */
79392  Group.findOrCreate = function(options) {
79393    return groups[options.axis][options.name] || new Group(options)
79394  }
79395
79396  Waypoint.Group = Group
79397}())
79398;(function() {
79399  'use strict'
79400
79401  var $ = window.jQuery
79402  var Waypoint = window.Waypoint
79403
79404  function JQueryAdapter(element) {
79405    this.$element = $(element)
79406  }
79407
79408  $.each([
79409    'innerHeight',
79410    'innerWidth',
79411    'off',
79412    'offset',
79413    'on',
79414    'outerHeight',
79415    'outerWidth',
79416    'scrollLeft',
79417    'scrollTop'
79418  ], function(i, method) {
79419    JQueryAdapter.prototype[method] = function() {
79420      var args = Array.prototype.slice.call(arguments)
79421      return this.$element[method].apply(this.$element, args)
79422    }
79423  })
79424
79425  $.each([
79426    'extend',
79427    'inArray',
79428    'isEmptyObject'
79429  ], function(i, method) {
79430    JQueryAdapter[method] = $[method]
79431  })
79432
79433  Waypoint.adapters.push({
79434    name: 'jquery',
79435    Adapter: JQueryAdapter
79436  })
79437  Waypoint.Adapter = JQueryAdapter
79438}())
79439;(function() {
79440  'use strict'
79441
79442  var Waypoint = window.Waypoint
79443
79444  function createExtension(framework) {
79445    return function() {
79446      var waypoints = []
79447      var overrides = arguments[0]
79448
79449      if (framework.isFunction(arguments[0])) {
79450        overrides = framework.extend({}, arguments[1])
79451        overrides.handler = arguments[0]
79452      }
79453
79454      this.each(function() {
79455        var options = framework.extend({}, overrides, {
79456          element: this
79457        })
79458        if (typeof options.context === 'string') {
79459          options.context = framework(this).closest(options.context)[0]
79460        }
79461        waypoints.push(new Waypoint(options))
79462      })
79463
79464      return waypoints
79465    }
79466  }
79467
79468  if (window.jQuery) {
79469    window.jQuery.fn.waypoint = createExtension(window.jQuery)
79470  }
79471  if (window.Zepto) {
79472    window.Zepto.fn.waypoint = createExtension(window.Zepto)
79473  }
79474}())
79475;
79476/*!
79477* jquery.counterup.js 1.0
79478*
79479* Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
79480* Released under the GPL v2 License
79481*
79482* Date: Nov 26, 2013
79483*/
79484!function(t){"use strict";t.fn.counterUp=function(e){var u=t.extend({time:400,delay:10},e);return this.each(function(){var e=t(this),n=u,a=function(){var t=n.time/n.delay,u=e.attr("data-value"),a=[u],r=/[0-9]+,[0-9]+/.test(u);u=u.replace(/,/g,"");for(var o=(/^[0-9]+$/.test(u),/^[0-9]+\.[0-9]+$/.test(u)),c=o?(u.split(".")[1]||[]).length:0,d=t;d>=1;d--){var s=parseInt(u/t*d);if(o&&(s=parseFloat(u/t*d).toFixed(c)),r)for(;/(\d+)(\d{3})/.test(s.toString());)s=s.toString().replace(/(\d+)(\d{3})/,"$1,$2");a.unshift(s)}e.data("counterup-nums",a),e.text("0");var i=function(){e.data("counterup-nums")&&(e.text(e.data("counterup-nums").shift()),e.data("counterup-nums").length?setTimeout(e.data("counterup-func"),n.delay):(delete e.data("counterup-nums"),e.data("counterup-nums",null),e.data("counterup-func",null)))};e.data("counterup-func",i),setTimeout(e.data("counterup-func"),n.delay)};e.waypoint(a,{offset:"100%",triggerOnce:!0})})}}(jQuery);
79485
79486(function(t){function z(){for(var a=0;a<g.length;a++)g[a][0](g[a][1]);g=[];m=!1}function n(a,b){g.push([a,b]);m||(m=!0,A(z,0))}function B(a,b){function c(a){p(b,a)}function h(a){k(b,a)}try{a(c,h)}catch(d){h(d)}}function u(a){var b=a.owner,c=b.state_,b=b.data_,h=a[c];a=a.then;if("function"===typeof h){c=l;try{b=h(b)}catch(d){k(a,d)}}v(a,b)||(c===l&&p(a,b),c===q&&k(a,b))}function v(a,b){var c;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(b&&("function"===
79487typeof b||"object"===typeof b)){var h=b.then;if("function"===typeof h)return h.call(b,function(d){c||(c=!0,b!==d?p(a,d):w(a,d))},function(b){c||(c=!0,k(a,b))}),!0}}catch(d){return c||k(a,d),!0}return!1}function p(a,b){a!==b&&v(a,b)||w(a,b)}function w(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(C,a))}function k(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(D,a))}function y(a){var b=a.then_;a.then_=void 0;for(a=0;a<b.length;a++)u(b[a])}function C(a){a.state_=l;y(a)}function D(a){a.state_=q;y(a)}function e(a){if("function"!==
79488typeof a)throw new TypeError("Promise constructor takes a function argument");if(!1===this instanceof e)throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object c
79488onstructor cannot be called as a function.");this.then_=[];B(a,this)}var f=t.Promise,s=f&&"resolve"in f&&"reject"in f&&"all"in f&&"race"in f&&function(){var a;new f(function(b){a=b});return"function"===typeof a}();"undefined"!==typeof exports&&exports?(exports.Promise=s?f:e,exports.Polyfill=e):"function"==
79489typeof define&&define.amd?define(function(){return s?f:e}):s||(t.Promise=e);var r="pending",x="sealed",l="fulfilled",q="rejected",E=function(){},A="undefined"!==typeof setImmediate?setImmediate:setTimeout,g=[],m;e.prototype={constructor:e,state_:r,then_:null,data_:void 0,then:function(a,b){var c={owner:this,then:new this.constructor(E),fulfilled:a,rejected:b};this.state_===l||this.state_===q?n(u,c):this.then_.push(c);return c.then},"catch":function(a){return this.then(null,a)}};e.all=function(a){if("[object Array]"!==
79490Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.all().");return new this(function(b,c){function h(a){e++;return function(c){d[a]=c;--e||b(d)}}for(var d=[],e=0,f=0,g;f<a.length;f++)(g=a[f])&&"function"===typeof g.then?g.then(h(f),c):d[f]=g;e||b(d)})};e.race=function(a){if("[object Array]"!==Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.race().");return new this(function(b,c){for(var e=0,d;e<a.length;e++)(d=a[e])&&"function"===
79491typeof d.then?d.then(b,c):b(d)})};e.resolve=function(a){return a&&"object"===typeof a&&a.constructor===this?a:new this(function(b){b(a)})};e.reject=function(a){return new this(function(b,c){c(a)})}})("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this);
79492
79493!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Sweetalert2=t()}(this,function(){"use strict";function q(e){return(q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function i(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}function r(){return(r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e}).apply(this,arguments)}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&u(e,t)}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){return(u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function l(e,t,n){return(l=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,n){var o=[null];o.push.apply(o,t);var i=new(Function.bind.apply(e,o));return n&&u(i,n.prototype),i}).apply(null,arguments)}function d(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function p(e,t,n){return(p="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,n){var o=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=c(e)););return e}(e,t);if(o){var i=Object.getOwnPropertyDescriptor(o,t);return i.get?i.get.call(n):i.value}})(e,t,n||e)}var t="SweetAlert2:",f=function(e){return Array.prototype.slice.call(e)},R=function(e){console.warn("".concat(t," ").concat(e))},I=function(e){console.error("".concat(t," ").concat(e))},n=[],m=function(e){-1===n.indexOf(e)&&(n.push(e),R(e))},H=function(e){return"function"==typeof e?e():e},D=function(e){return e&&Promise.resolve(e)===e},e=Object.freeze({cancel:"cancel",backdrop:"overlay",close:"close",esc:"esc",timer:"timer"}),h=function(e){var t={};for(var n in e)t[e[n]]="swal2-"+e[n];return t},_=h(["container","shown","height-auto","iosfix","popup","modal","no-backdrop","toast","toast-shown","toast-column","fade","show","hide","noanimation","close","title","header","content","actions","confirm","cancel","footer","icon","icon-text","image","input","file","range","select","radio","checkbox","label","textarea","inputerror","validation-message","progresssteps","activeprogressstep","progresscircle","progressline","loading","styled","top","top-start","to
79493p-end","top-left","top-right","center","center-start","center-end","center-left","center-right","bottom","bottom-start","bottom-end","bottom-left","bottom-right","grow-row","grow-column","grow-fullscreen","rtl"]),g=h(["success","warning","info","question","error"]),b={previousBodyPadding:null},v=function(e,t){return e.classList.contains(t)},N=function(e){if(e.focus(),"file"!==e.type){var t=e.value;e.value="",e.value=t}},y=function(e,t,n){e&&t&&("string"==typeof t&&(t=t.split(/\s+/).filter(Boolean)),t.forEach(function(t){e.forEach?e.forEach(function(e){n?e.classList.add(t):e.classList.remove(t)}):n?e.classList.add(t):e.classList.remove(t)}))},z=function(e,t){y(e,t,!0)},W=function(e,t){y(e,t,!1)},U=function(e,t){for(var n=0;n<e.childNodes.length;n++)if(v(e.childNodes[n],t))return e.childNodes[n]},K=function(e){e.style.opacity="",e.style.display=e.id===_.content?"block":"flex"},F=function(e){e.style.opacity="",e.style.display="none"},Z=function(e){return e&&(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w=function(){return document.body.querySelector("."+_.container)},C=function(e){var t=w();return t?t.querySelector("."+e):null},k=function(){return C(_.popup)},x=function(){var e=k();return f(e.querySelectorAll("."+_.icon))},A=function(){return C(_.title)},B=function(){return C(_.content)},S=function(){return C(_.image)},P=function(){return C(_.progresssteps)},E=function(){return C(_["validation-message"])},L=function(){return C(_.confirm)},O=function(){return C(_.cancel)},Q=function(){return C(_.actions)},Y=function(){return C(_.footer)},$=function(){return C(_.close)},J=function(){var e=f(k().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')).sort(function(e,t){return e=parseInt(e.getAttribute("tabindex")),(t=parseInt(t.getAttribute("tabindex")))<e?1:e<t?-1:0}),t=f(k().querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable], audio[controls], video[controls]')).filter(function(e){return"-1"!==e.getAttribute("tabindex")});return function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}(e.concat(t)).filter(function(e){return Z(e)})},T=function(){return!M()&&!document.body.classList.contains(_["no-backdrop"])},M=function(){return document.body.classList.contains(_["toast-shown"])},j=function(){return"undefined"==typeof window||"undefined"==typeof document},V='\n <div aria-labelledby="'.concat(_.title,'" aria-describedby="').concat(_.content,'" class="').concat(_.popup,'" tabindex="-1">\n   <div class="').concat(_.header,'">\n     <ul class="').concat(_.progresssteps,'"></ul>\n     <div class="').concat(_.icon," ").concat(g.error,'">\n       <span class="swal2-x-mark"><span class="swal2-x-mark-line-left"></span><span class="swal2-x-mark-line-right"></span></span>\n     </div>\n     <div class="').concat(_.icon," ").concat(g.question,'">\n       <span class="').concat(_["icon-text"],'">?</span>\n      </div>\n     <div class="').concat(_.icon," ").concat(g.warning,'">\n       <span class="').concat(_["icon-text"],'">!</span>\n      </div>\n     <div class="').concat(_.icon," ").concat(g.info,'">\n       <span class="').concat(_["icon-text"],'">i</span>\n      </div>\n     <div class="').concat(_.icon," ").concat(g.success,'">\n       <div class="swal2-success-circular-line-left"></div>\n       <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>\n       <div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>\n       <div class="swal2-success-circular-line-right"></div>\n     </div>\n     <img class="').concat(_.image,'" />\n     <h2 class="').concat(_.title,'" id="').concat(_.title,'"></h2>\n     <button type="button" class="').concat(_.close,'">×</button>\n   </div>\n   <div class="').concat(_.content,'">\n     <div id="').concat(_.content,'"></div>\n     <input class="').concat(_.input,'" />\n     <input type="file" class="').concat(_.file,'" />\n     <div class="').concat(_.range,'">\n       <input type="range" />\n       <output></output>\n     </div>\n     <select class="').concat(_.select,'"></select>\n     <div class="').concat(_.radio,'"></div>
79493\n     <label for="').concat(_.checkbox,'" class="').concat(_.checkbox,'">\n       <input type="checkbox" />\n       <span class="').concat(_.label,'"></span>\n     </label>\n     <textarea class="').concat(_.textarea,'"></textarea>\n     <div class="').concat(_["validation-message"],'" id="').concat(_["validation-message"],'"></div>\n   </div>\n   <div class="').concat(_.actions,'">\n     <button type="button" class="').concat(_.confirm,'">OK</button>\n     <button type="button" class="').concat(_.cancel,'">Cancel</button>\n   </div>\n   <div class="').concat(_.footer,'">\n   </div>\n </div>\n').replace(/(^|\n)\s*/g,""),X=function(e){var t=w();if(t&&(t.parentNode.removeChild(t),W([document.documentElement,document.body],[_["no-backdrop"],_["toast-shown"],_["has-column"]])),!j()){var n=document.createElement("div");n.className=_.container,n.innerHTML=V;var o="string"==typeof e.target?document.querySelector(e.target):e.target;o.appendChild(n);var i,r=k(),a=B(),s=U(a,_.input),c=U(a,_.file),u=a.querySelector(".".concat(_.range," input")),l=a.querySelector(".".concat(_.range," output")),d=U(a,_.select),p=a.querySelector(".".concat(_.checkbox," input")),f=U(a,_.textarea);r.setAttribute("role",e.toast?"alert":"dialog"),r.setAttribute("aria-live",e.toast?"polite":"assertive"),e.toast||r.setAttribute("aria-modal","true"),"rtl"===window.getComputedStyle(o).direction&&z(w(),_.rtl);var m=function(e){De.isVisible()&&i!==e.target.value&&De.resetValidationMessage(),i=e.target.value};return s.oninput=m,c.onchange=m,d.onchange=m,p.onchange=m,f.oninput=m,u.oninput=function(e){m(e),l.value=u.value},u.onchange=function(e){m(e),u.nextSibling.value=u.value},r}I("SweetAlert2 requires document to initialize")},G=function(e,t){if(!e)return F(t);if(e instanceof HTMLElement)t.appendChild(e);else if("object"===q(e))if(t.innerHTML="",0 in e)for(var n=0;n in e;n++)t.appendChild(e[n].cloneNode(!0));else t.appendChild(e.cloneNode(!0));else e&&(t.innerHTML=e);K(t)},ee=function(){if(j())return!1;var e=document.createElement("div"),t={WebkitAnimation:"webkitAnimationEnd",OAnimation:"oAnimationEnd oanimationend",animation:"animationend"};for(var n in t)if(t.hasOwnProperty(n)&&void 0!==e.style[n])return t[n];return!1}(),te=function(e){var t=Q(),n=L(),o=O();if(e.showConfirmButton||e.showCancelButton?K(t):F(t),e.showCancelButton?o.style.display="inline-block":F(o),e.showConfirmButton?n.style.removeProperty("display"):F(n),n.innerHTML=e.confirmButtonText,o.innerHTML=e.cancelButtonText,n.setAttribute("aria-label",e.confirmButtonAriaLabel),o.setAttribute("aria-label",e.cancelButtonAriaLabel),n.className=_.confirm,z(n,e.confirmButtonClass),o.className=_.cancel,z(o,e.cancelButtonClass),e.buttonsStyling){z([n,o],_.styled),e.confirmButtonColor&&(n.style.backgroundColor=e.confirmButtonColor),e.cancelButtonColor&&(o.style.backgroundColor=e.cancelButtonColor);var i=window.getComputedStyle(n).getPropertyValue("background-color");n.style.borderLeftColor=i,n.style.borderRightColor=i}else W([n,o],_.styled),n.style.backgroundColor=n.style.borderLeftColor=n.style.borderRightColor="",o.style.backgroundColor=o.style.borderLeftColor=o.style.borderRightColor=""},ne=function(e){var t=B().querySelector("#"+_.content);e.html?G(e.html,t):e.text?(t.textContent=e.text,K(t)):F(t)},oe=function(e){for(var t=x(),n=0;n<t.length;n++)F(t[n]);if(e.type)if(-1!==Object.keys(g).indexOf(e.type)){var o=De.getPopup().querySelector(".".concat(_.icon,".").concat(g[e.type]));K(o),e.animation&&z(o,"swal2-animate-".concat(e.type,"-icon"))}else I('Unknown type! Expected "success", "error", "warning", "info" or "question", got "'.concat(e.type,'"'))},ie=function(e){var t=S();e.imageUrl?(t.setAttribute("src",e.imageUrl),t.setAttribute("alt",e.imageAlt),K(t),e.imageWidth?t.setAttribute("width",e.imageWidth):t.removeAttribute("width"),e.imageHeight?t.setAttribute("height",e.imageHeight):t.removeAttribute("height"),t.className=_.image,e.imageClass&&z(t,e.imageClass)):F(t)},re=function(i){var r=P(),a=parseInt(null===i.currentProgressStep?De.getQueueStep():i.currentProgressStep,10);i.progressSteps&&i.progressSteps.length?(K(r),r.innerHTML="",a>=i.progressSteps.length&&R("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),i.progressSteps.forEach(function(e,t){var n=document.createElement("li");if(z(n,_.progresscircle),n.innerHTML=e,t===a&&z(n,_.activeprogressstep),r.appendChild(n),t!==i.progressSteps.length-1){var o=document.createElement("li");z(o,_.progressline),i.progressStepsDistance&&(o.style.width=i.progressStepsDistance),r.appendChild(o)}})):F(r)},ae=function(e){var t=A();e.titleText?t.innerText=e.titleText:e.title&&("string"==typeof e.title&&(e.title=e.title.split("\n").join("<br />")),G(e.title,t))},se=function(){null===b.previousBodyPadding&&document.body.scrollHeight>window.innerHeight&&(b.previousBodyPadding=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")),document.body.style.paddingRight=b.previousBodyPadding+function(){if("ontouchstart"in window||navigator.msMaxTouchPoints)return 0;var e=document.createElement("div");
79493e.style.width="50px",e.style.height="50px",e.style.overflow="scroll",document.body.appendChild(e);var t=e.offsetWidth-e.clientWidth;return document.body.removeChild(e),t}()+"px")},ce=function(){return!!window.MSInputMethodContext&&!!document.documentMode},ue=function(){var e=w(),t=k();e.style.removeProperty("align-items"),t.offsetTop<0&&(e.style.alignItems="flex-start")},le={},de=function(e,t){var n=w(),o=k();if(o){null!==e&&"function"==typeof e&&e(o),W(o,_.show),z(o,_.hide);var i=function(){M()?pe(t):(new Promise(function(e){var t=window.scrollX,n=window.scrollY;le.restoreFocusTimeout=setTimeout(function(){le.previousActiveElement&&le.previousActiveElement.focus?(le.previousActiveElement.focus(),le.previousActiveElement=null):document.body&&document.body.focus(),e()},100),void 0!==t&&void 0!==n&&window.scrollTo(t,n)}).then(function(){return pe(t)}),le.keydownTarget.removeEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!1),n.parentNode&&n.parentNode.removeChild(n),W([document.documentElement,document.body],[_.shown,_["height-auto"],_["no-backdrop"],_["toast-shown"],_["toast-column"]]),T()&&(null!==b.previousBodyPadding&&(document.body.style.paddingRight=b.previousBodyPadding,b.previousBodyPadding=null),function(){if(v(document.body,_.iosfix)){var e=parseInt(document.body.style.top,10);W(document.body,_.iosfix),document.body.style.top="",document.body.scrollTop=-1*e}}(),"undefined"!=typeof window&&ce()&&window.removeEventListener("resize",ue),f(document.body.children).forEach(function(e){e.hasAttribute("data-previous-aria-hidden")?(e.setAttribute("aria-hidden",e.getAttribute("data-previous-aria-hidden")),e.removeAttribute("data-previous-aria-hidden")):e.removeAttribute("aria-hidden")}))};ee&&!v(o,_.noanimation)?o.addEventListener(ee,function e(){o.removeEventListener(ee,e),v(o,_.hide)&&i()}):i()}},pe=function(e){null!==e&&"function"==typeof e&&setTimeout(function(){e()})};function fe(e){var t=function e(){for(var t=arguments.length,n=new Array(t),o=0;o<t;o++)n[o]=arguments[o];if(!(this instanceof e))return l(e,n);Object.getPrototypeOf(e).apply(this,n)};return t.prototype=r(Object.create(e.prototype),{constructor:t}),"function"==typeof Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e,t}var me={title:"",titleText:"",text:"",html:"",footer:"",type:null,toast:!1,customClass:"",customContainerClass:"",target:"body",backdrop:!0,animation:!0,heightAuto:!0,allowOutsideClick:!0,allowEscapeKey:!0,allowEnterKey:!0,stopKeydownPropagation:!0,keydownListenerCapture:!1,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonAriaLabel:"",confirmButtonColor:null,confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonAriaLabel:"",cancelButtonColor:null,cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,focusConfirm:!0,focusCancel:!1,showCloseButton:!1,closeButtonAriaLabel:"Close this dialog",showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageAlt:"",imageClass:null,timer:null,width:null,padding:null,background:null,input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,validationMessage:null,grow:!1,position:"center",progressSteps:[],currentProgressStep:null,progressStepsDistance:null,onBeforeOpen:null,onAfterClose:null,onOpen:null,onClose:null,useRejections:!1,expectRejections:!1},he=["useRejections","expectRejections","extraParams"],ge=["allowOutsideClick","allowEnterKey","backdrop","focusConfirm","focusCancel","heightAuto","keydownListenerCapture"],be=function(e){return me.hasOwnProperty(e)||"extraParams"===e},ve=function(e){return-1!==he.indexOf(e)},ye=function(e){for(var t in e)be(t)||R('Unknown parameter "'.concat(t,'"')),e.toast&&-1!==ge.indexOf(t)&&R('The parameter "'.concat(t,'" is incompatible with toasts')),ve(t)&&m('The parameter "'.concat(t,'" is deprecated and will be removed in the next major release.'))}
79493,we='"setDefaults" & "resetDefaults" methods are deprecated in favor of "mixin" method and will be removed in the next major release. For new projects, use "mixin". For past projects already using "setDefaults", support will be provided through an additional package.',Ce={};var ke=[],xe=function(){var e=k();e||De(""),e=k();var t=Q(),n=L(),o=O();K(t),K(n),z([e,t],_.loading),n.disabled=!0,o.disabled=!0,e.setAttribute("data-loading",!0),e.setAttribute("aria-busy",!0),e.focus()},Ae=Object.freeze({isValidParameter:be,isDeprecatedParameter:ve,argsToParams:function(n){var o={};switch(q(n[0])){case"object":r(o,n[0]);break;default:["title","html","type"].forEach(function(e,t){switch(q(n[t])){case"string":o[e]=n[t];break;case"undefined":break;default:I("Unexpected type of ".concat(e,'! Expected "string", got ').concat(q(n[t])))}})}return o},adaptInputValidator:function(n){return function(e,t){return n.call(this,e,t).then(function(){},function(e){return e})}},close:de,closePopup:de,closeModal:de,closeToast:de,isVisible:function(){return!!k()},clickConfirm:function(){return L().click()},clickCancel:function(){return O().click()},getContainer:w,getPopup:k,getTitle:A,getContent:B,getImage:S,getIcons:x,getCloseButton:$,getButtonsWrapper:function(){return m("swal.getButtonsWrapper() is deprecated and will be removed in the next major release, use swal.getActions() instead"),C(_.actions)},getActions:Q,getConfirmButton:L,getCancelButton:O,getFooter:Y,getFocusableElements:J,getValidationMessage:E,isLoading:function(){return k().hasAttribute("data-loading")},fire:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return l(this,t)},mixin:function(n){return fe(function(e){function t(){return a(this,t),d(this,c(t).apply(this,arguments))}return s(t,e),i(t,[{key:"_main",value:function(e){return p(c(t.prototype),"_main",this).call(this,r({},n,e))}}]),t}(this))},queue:function(e){var r=this;ke=e;var a=function(){ke=[],document.body.removeAttribute("data-swal2-queue-step")},s=[];return new Promise(function(i){!function t(n,o){n<ke.length?(document.body.setAttribute("data-swal2-queue-step",n),r(ke[n]).then(function(e){void 0!==e.value?(s.push(e.value),t(n+1,o)):(a(),i({dismiss:e.dismiss}))})):(a(),i({value:s}))}(0)})},getQueueStep:function(){return document.body.getAttribute("data-swal2-queue-step")},insertQueueStep:function(e,t){return t&&t<ke.length?ke.splice(t,0,e):ke.push(e)},deleteQueueStep:function(e){void 0!==ke[e]&&ke.splice(e,1)},showLoading:xe,enableLoading:xe,getTimerLeft:function(){return le.timeout&&le.timeout.getTimerLeft()},stopTimer:function(){return le.timeout&&le.timeout.stop()},resumeTimer:function(){return le.timeout&&le.timeout.start()},toggleTimer:function(){var e=le.timeout;return e&&(e.running?e.stop():e.start())},increaseTimer:function(e){return le.timeout&&le.timeout.increase(e)},isTimerRunning:function(){return le.timeout&&le.timeout.isRunning()}}),Be="function"==typeof Symbol?Symbol:function(){var t=0;function e(e){return"__"+e+"_"+Math.floor(1e9*Math.random())+"_"+ ++t+"__"}return e.iterator=e("Symbol.iterator"),e}(),Se="function"==typeof WeakMap?WeakMap:function(n,o,t){function e(){o(this,n,{value:Be("WeakMap")})}return e.prototype={delete:function(e){delete e[this[n]]},get:function(e){return e[this[n]]},has:function(e){return t.call(e,this[n])},set:function(e,t){o(e,this[n],{configurable:!0,value:t})}},e}(Be("WeakMap"),Object.defineProperty,{}.hasOwnProperty),Pe={promise:new Se,innerParams:new Se,domCache:new Se};function Ee(){var e=Pe.innerParams.get(this),t=Pe.domCache.get(this);e.showConfirmButton||(F(t.confirmButton),e.showCancelButton||F(t.actions)),W([t.popup,t.actions],_.loading),t.popup.removeAttribute("aria-busy"),t.popup.removeAttribute("data-loading"),t.confirmButton.disabled=!1,t.cancelButton.disabled=!1}function Le(e){var t=Pe.domCache.get(this);t.validationMessage.innerHTML=e;var n=window.getComputedStyle(t.popup);t.validationMessage.style.marginLeft="-".concat(n.getPropertyValue("padding-left")),t.validationMessage.style.marginRight="-".concat(n.getPropertyValue("padding-right")),K(t.validationMessage);var o=this.getInput();o&&(o.setAttribute("aria-invalid",!0),o.setAttribute("aria-describedBy",_["validation-message"]),N(o),z(o,_.
79493inputerror))}function Oe(){var e=Pe.domCache.get(this);e.validationMessage&&F(e.validationMessage);var t=this.getInput();t&&(t.removeAttribute("aria-invalid"),t.removeAttribute("aria-describedBy"),W(t,_.inputerror))}var Te=function e(t,n){a(this,e);var o,i,r=n;this.running=!1,this.start=function(){return this.running||(this.running=!0,i=new Date,o=setTimeout(t,r)),r},this.stop=function(){return this.running&&(this.running=!1,clearTimeout(o),r-=new Date-i),r},this.increase=function(e){var t=this.running;return t&&this.stop(),r+=e,t&&this.start(),r},this.getTimerLeft=function(){return this.running&&(this.stop(),this.start()),r},this.isRunning=function(){return this.running},this.start()},Me={email:function(e,t){return/^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(e)?Promise.resolve():Promise.reject(t&&t.validationMessage?t.validationMessage:"Invalid email address")},url:function(e,t){return/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)$/.test(e)?Promise.resolve():Promise.reject(t&&t.validationMessage?t.validationMessage:"Invalid URL")}};var je=function(e){var t=w(),n=k();null!==e.onBeforeOpen&&"function"==typeof e.onBeforeOpen&&e.onBeforeOpen(n),e.animation?(z(n,_.show),z(t,_.fade),W(n,_.hide)):W(n,_.fade),K(n),t.style.overflowY="hidden",ee&&!v(n,_.noanimation)?n.addEventListener(ee,function e(){n.removeEventListener(ee,e),t.style.overflowY="auto"}):t.style.overflowY="auto",z([document.documentElement,document.body,t],_.shown),e.heightAuto&&e.backdrop&&!e.toast&&z([document.documentElement,document.body],_["height-auto"]),T()&&(se(),function(){if(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream&&!v(document.body,_.iosfix)){var e=document.body.scrollTop;document.body.style.top=-1*e+"px",z(document.body,_.iosfix)}}(),"undefined"!=typeof window&&ce()&&(ue(),window.addEventListener("resize",ue)),f(document.body.children).forEach(function(e){e===w()||function(e,t){if("function"==typeof e.contains)return e.contains(t)}(e,w())||(e.hasAttribute("aria-hidden")&&e.setAttribute("data-previous-aria-hidden",e.getAttribute("aria-hidden")),e.setAttribute("aria-hidden","true"))}),setTimeout(function(){t.scrollTop=0})),M()||le.previousActiveElement||(le.previousActiveElement=document.activeElement),null!==e.onOpen&&"function"==typeof e.onOpen&&setTimeout(function(){e.onOpen(n)})};var Ve,qe=Object.freeze({hideLoading:Ee,disableLoading:Ee,getInput:function(e){var t=Pe.innerParams.get(this),n=Pe.domCache.get(this);if(!(e=e||t.input))return null;switch(e){case"select":case"textarea":case"file":return U(n.content,_[e]);case"checkbox":return n.popup.querySelector(".".concat(_.checkbox," input"));case"radio":return n.popup.querySelector(".".concat(_.radio," input:checked"))||n.popup.querySelector(".".concat(_.radio," input:first-child"));case"range":return n.popup.querySelector(".".concat(_.range," input"));default:return U(n.content,_.input)}},enableButtons:function(){var e=Pe.domCache.get(this);e.confirmButton.disabled=!1,e.cancelButton.disabled=!1},disableButtons:function(){var e=Pe.domCache.get(this);e.confirmButton.disabled=!0,e.cancelButton.disabled=!0},enableConfirmButton:function(){Pe.domCache.get(this).confirmButton.disabled=!1},disableConfirmButton:function(){Pe.domCache.get(this).confirmButton.disabled=!0},enableInput:function(){var e=this.getInput();if(!e)return!1;if("radio"===e.type)for(var t=e.parentNode.parentNode.querySelectorAll("input"),n=0;n<t.length;n++)t[n].disabled=!1;else e.disabled=!1},disableInput:function(){var e=this.getInput();if(!e)return!1;if(e&&"radio"===e.type)for(var t=e.parentNode.parentNode.querySelectorAll("input"),n=0;n<t.length;n++)t[n].disabled=!0;else e.disabled=!0},showValidationMessage:Le,resetValidationMessage:Oe,resetValidationError:function(){m("Swal.resetValidationError() is deprecated and will be removed in the next major release, use Swal.resetValidationMessage() instead"),Oe.bind(this)()},showValidationError:function(e){m("Swal.showValidationError() is deprecated and will be removed in the next major release, use Swal.showValidationMessage() instead"),Le.bind(this)(e)},getProgressSteps:function(){return Pe.innerParams.get(this).progressSteps},setProgressSteps:function(e){var t=r({},Pe.innerParams.get(this),{progressSteps:e});Pe.innerParams.set(this,t),re(t)},showProgressSteps:function(){var e=Pe.domCache.get(this);K(e.progressSteps)},hideProgressSteps:function(){var e=Pe.domCache.get(this);F(e.progressSteps)},_main:function(e){var T=this;ye(e);var M=r({},me,e);!function(t){var e;
79493t.inputValidator||Object.keys(Me).forEach(function(e){t.input===e&&(t.inputValidator=t.expectRejections?Me[e]:De.adaptInputValidator(Me[e]))}),t.validationMessage&&("object"!==q(t.extraParams)&&(t.extraParams={}),t.extraParams.validationMessage=t.validationMessage),(!t.target||"string"==typeof t.target&&!document.querySelector(t.target)||"string"!=typeof t.target&&!t.target.appendChild)&&(R('Target parameter is not valid, defaulting to "body"'),t.target="body"),"function"==typeof t.animation&&(t.animation=t.animation.call());var n=k(),o="string"==typeof t.target?document.querySelector(t.target):t.target;e=n&&o&&n.parentNode!==o.parentNode?X(t):n||X(t),t.width&&(e.style.width="number"==typeof t.width?t.width+"px":t.width),t.padding&&(e.style.padding="number"==typeof t.padding?t.padding+"px":t.padding),t.background&&(e.style.background=t.background);for(var i=window.getComputedStyle(e).getPropertyValue("background-color"),r=e.querySelectorAll("[class^=swal2-success-circular-line], .swal2-success-fix"),a=0;a<r.length;a++)r[a].style.backgroundColor=i;var s=w(),c=$(),u=Y();if(ae(t),ne(t),"string"==typeof t.backdrop?w().style.background=t.backdrop:t.backdrop||z([document.documentElement,document.body],_["no-backdrop"]),!t.backdrop&&t.allowOutsideClick&&R('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`'),t.position in _?z(s,_[t.position]):(R('The "position" parameter is not valid, defaulting to "center"'),z(s,_.center)),t.grow&&"string"==typeof t.grow){var l="grow-"+t.grow;l in _&&z(s,_[l])}t.showCloseButton?(c.setAttribute("aria-label",t.closeButtonAriaLabel),K(c)):F(c),e.className=_.popup,t.toast?(z([document.documentElement,document.body],_["toast-shown"]),z(e,_.toast)):z(e,_.modal),t.customClass&&z(e,t.customClass),t.customContainerClass&&z(s,t.customContainerClass),re(t),oe(t),ie(t),te(t),G(t.footer,u),!0===t.animation?W(e,_.noanimation):z(e,_.noanimation),t.showLoaderOnConfirm&&!t.preConfirm&&R("showLoaderOnConfirm is set to true, but preConfirm is not defined.\nshowLoaderOnConfirm should be used together with preConfirm, see usage example:\nhttps://sweetalert2.github.io/#ajax-request")}(M),Object.freeze(M),Pe.innerParams.set(this,M),le.timeout&&(le.timeout.stop(),delete le.t
79493imeout),clearTimeout(le.restoreFocusTimeout);var j={popup:k(),container:w(),content:B(),actions:Q(),confirmButton:L(),cancelButton:O(),closeButton:$(),validationMessage:E(),progressSteps:P()};Pe.domCache.set(this,j);var V=this.constructor;return new Promise(function(t,n){var o=function(e){V.closePopup(M.onClose,M.onAfterClose),M.useRejections?t(e):t({value:e})},c=function(e){V.closePopup(M.onClose,M.onAfterClose),M.useRejections?n(e):t({dismiss:e})},u=function(e){V.closePopup(M.onClose,M.onAfterClose),n(e)};M.timer&&(le.timeout=new Te(function(){c("timer"),delete le.timeout},M.timer)),M.input&&setTimeout(function(){var e=T.getInput();e&&N(e)},0);for(var l=function(t){if(M.showLoaderOnConfirm&&V.showLoading(),M.preConfirm){T.resetValidationMessage();var e=Promise.resolve().then(function(){return M.preConfirm(t,M.extraParams)});M.expectRejections?e.then(function(e){return o(e||t)},function(e){T.hideLoading(),e&&T.showValidationMessage(e)}):e.then(function(e){Z(j.validationMessage)||!1===e?T.hideLoading():o(e||t)},function(e){return u(e)})}else o(t)},e=function(e){var t=e.target,n=j.confirmButton,o=j.cancelButton,i=n&&(n===t||n.contains(t)),r=o&&(o===t||o.contains(t));switch(e.type){case"click":if(i&&V.isVisible())if(T.disableButtons(),M.input){var a=function(){var e=T.getInput();if(!e)return null;switch(M.input){case"checkbox":return e.checked?1:0;case"radio":return e.checked?e.value:null;case"file":return e.files.length?e.files[0]:null;default:return M.inputAutoTrim?e.value.trim():e.value}}();if(M.inputValidator){T.disableInput();var s=Promise.resolve().then(function(){return M.inputValidator(a,M.extraParams)});M.expectRejections?s.then(function(){T.enableButtons(),T.enableInput(),l(a)},function(e){T.enableButtons(),T.enableInput(),e&&T.showValidationMessage(e)}):s.then(function(e){T.enableButtons(),T.enableInput(),e?T.showValidationMessage(e):l(a)},function(e){return u(e)})}else T.getInput().checkValidity()?l(a):(T.enableButtons(),T.showValidationMessage(M.validationMessage))}else l(!0);else r&&V.isVisible()&&(T.disableButtons(),c(V.DismissReason.cancel))}},i=j.popup.querySelectorAll("button"),r=0;r<i.length;r++)i[r].onclick=e,i[r].onmouseover=e,i[r].onmouseout=e,i[r].onmousedown=e;if(j.closeButton.onclick=function(){c(V.DismissReason.close)},M.toast)j.popup.onclick=function(){M.showConfirmButton||M.showCancelButton||M.showCloseButton||M.input||c(V.DismissReason.close)};else{var a=!1;j.popup.onmousedown=function(){j.container.onmouseup=function(e){j.container.onmouseup=void 0,e.target===j.container&&(a=!0)}},j.container.onmousedown=function(){j.popup.onmouseup=function(e){j.popup.onmouseup=void 0,(e.target===j.popup||j.popup.contains(e.target))&&(a=!0)}},j.container.onclick=function(e){a?a=!1:e.target===j.container&&H(M.allowOutsideClick)&&c(V.DismissReason.backdrop)}}M.reverseButtons?j.confirmButton.parentNode.insertBefore(j.cancelButton,j.confirmButton):j.confirmButton.parentNode.insertBefore(j.confirmButton,j.cancelButton);var s=function(e,t){for(var n=J(M.focusCancel),o=0;o<n.length;o++)return(e+=t)===n.length?e=0:-1===e&&(e=n.length-1),n[e].focus();j.popup.focus()};le.keydownHandlerAdded&&(le.keydownTarget.removeEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!1),M.toast||(le.keydownHandler=function(e){return function(e,t){if(t.stopKeydownPropagation&&e.stopPropagation(),"Enter"!==e.key||e.isComposing)if("Tab"===e.key){for(var n=e.target,o=J(t.focusCancel),i=-1,r=0;r<o.length;r++)if(n===o[r]){i=r;break}e.shiftKey?s(i,-1):s(i,1),e.stopPropagation(),e.preventDefault()}else-1!==["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Left","Right","Up","Down"].indexOf(e.key)?document.activeElement===j.confirmButton&&Z(j.cancelButton)?j.cancelButton.focus():document.activeElement===j.cancelButton&&Z(j.confirmButton)&&j.confirmButton.focus():"Escape"!==e.key&&"Esc"!==e.key||!0!==H(t.allowEscapeKey)||(e.preventDefault(),c(V.DismissReason.esc));else if(e.target&&T.getInput()&&e.target.outerHTML===T.getInput().outerHTML){if(-1!==["textarea","file"].indexOf(t.input))return;V.clickConfirm(),e.preventDefault()}}(e,M)},le.keydownTarget=M.keydownListenerCapture?window:j.popup,le.keydownListenerCapture=M.keydownListenerCapture,le.keydownTarget.addEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!0),T.enableButtons(),T.hideLoading(),T.resetValidationMessage(),M.toast&&(M.input||M.footer||M.showCloseButton)?z(document.body,_["toast-column"]):W(document.body,_["toast-column"]);for(var d,p,f=["input","file","range","select","radio","checkbox","textarea"],m=function(e){e.placeholder&&!M.inputPlaceholder||(e.placeholder=M.inputPlaceholder)},h=0;h<f.length;h++){var g=_[f[h]],b=U(j.content,g);if(d=T.getInput(f[h])){for(var v in d.attributes)if(d.attributes.hasOwnProperty(v)){var y=d.attributes[v].name;"type"!==y&&"value"!==y&&d.removeAttribute(y)}for(var w in M.inputAttributes)"range"===f[h]&&"placeholder"===w||d.setAttribute(w,M.inputAttributes[w])}b.className=g,M.inputClass&&z(b,M.inputClass),F(b)}switch(M.input){case"text":case"email":case"password":case"number":case"tel":case"url":d=U(j.content,_.input),"string"==typeof M.inputValue||"number"==typeof M.inputValue?d.value=M.inputValue:D(M.inputValue)||R('Unexpected type of inputValue! Expected "string", "number" or "Promise", got "'.concat(q(M.inputValue),'"')),m(d),d.type=M.input,
79493K(d);break;case"file":m(d=U(j.content,_.file)),d.type=M.input,K(d);break;case"range":var C=U(j.content,_.range),k=C.querySelector("input"),x=C.querySelector("output");k.value=M.inputValue,k.type=M.input,x.value=M.inputValue,K(C);break;case"select":var A=U(j.content,_.select);if(A.innerHTML="",M.inputPlaceholder){var B=document.createElement("option");B.innerHTML=M.inputPlaceholder,B.value="",B.disabled=!0,B.selected=!0,A.appendChild(B)}p=function(e){e.forEach(function(e){var t=e[0],n=e[1],o=document.createElement("option");o.value=t,o.innerHTML=n,M.inputValue.toString()===t.toString()&&(o.selected=!0),A.appendChild(o)}),K(A),A.focus()};break;case"radio":var S=U(j.content,_.radio);S.innerHTML="",p=function(e){e.forEach(function(e){var t=e[0],n=e[1],o=document.createElement("input"),i=document.createElement("label");o.type="radio",o.name=_.radio,o.value=t,M.inputValue.toString()===t.toString()&&(o.checked=!0);var r=document.createElement("span");r.innerHTML=n,r.className=_.label,i.appendChild(o),i.appendChild(r),S.appendChild(i)}),K(S);var t=S.querySelectorAll("input");t.length&&t[0].focus()};break;case"checkbox":var P=U(j.content,_.checkbox),E=T.getInput("checkbox");E.type="checkbox",E.value=1,E.id=_.checkbox,E.checked=Boolean(M.inputValue),P.querySelector("span").innerHTML=M.inputPlaceholder,K(P);break;case"textarea":var L=U(j.content,_.textarea);L.value=M.inputValue,m(L),K(L);break;case null:break;default:I('Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "'.concat(M.input,'"'))}if("select"===M.input||"radio"===M.input){var O=function(e){return p((t=e,n=[],"undefined"!=typeof Map&&t instanceof Map?t.forEach(function(e,t){n.push([t,e])}):Object.keys(t).forEach(function(e){n.push([e,t[e]])}),n));var t,n};D(M.inputOptions)?(V.showLoading(),M.inputOptions.then(function(e){T.hideLoading(),O(e)})):"object"===q(M.inputOptions)?O(M.inputOptions):I("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(q(M.inputOptions)))}else-1!==["text","email","number","tel","textarea"].indexOf(M.input)&&D(M.inputValue)&&(V.showLoading(),F(d),M.inputValue.then(function(e){d.value="number"===M.input?parseFloat(e)||0:e+"",K(d),d.focus(),T.hideLoading()}).catch(function(e){I("Error in inputValue promise: "+e),d.value="",K(d),d.focus(),T.hideLoading()}));je(M),M.toast||(H(M.allowEnterKey)?M.focusCancel&&Z(j.cancelButton)?j.cancelButton.focus():M.focusConfirm&&Z(j.confirmButton)?j.confirmButton.focus():s(-1,1):document.activeElement&&"function"==typeof document.activeElement.blur&&document.activeElement.blur()),j.container.scrollTop=0})}});function Re(){if("undefined"!=typeof window){"undefined"==typeof Promise&&I("This package requires a Promise library, please include a shim to enable it in this browser (See: https://github.com/sweetalert2/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2#1-ie-support)"),Ve=this;for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var o=Object.freeze(this.constructor.argsToParams(t));Object.defineProperties(this,{params:{value:o,writable:!1,enumerable:!0}});var i=this._main(this.params);Pe.promise.set(this,i)}}Re.prototype.then=function(e,t){return Pe.promise.get(this).then(e,t)},Re.prototype.catch=function(e){return Pe.promise.get(this).catch(e)},Re.prototype.finally=function(e){return Pe.promise.get(this).finally(e)},r(Re.prototype,qe),r(Re,Ae),Object.keys(qe).forEach(function(t){Re[t]=function(){var e;if(Ve)return(e=Ve)[t].apply(e,arguments)}}),Re.DismissReason=e,Re.noop=function(){};var Ie,He,De=fe((Ie=Re,He=function(e){function t(){return a(this,t),d(this,c(t).apply(this,arguments))}return s(t,Ie),i(t,[{key:"_main",value:function(e){return p(c(t.prototype),"_main",this).call(this,r({},Ce,e))}}],[{key:"setDefaults",value:function(t){if(m(we),!t||"object"!==q(t))throw new TypeError("SweetAlert2: The argument for setDefaults() is required and has to be a object");ye(t),Object.keys(t).forEach(function(e){Ie.isValidParameter(e)&&(Ce[e]=t[e])})}},{key:"resetDefaults",value:function(){m(we),Ce={}}}]),t}(),"undefined"!=typeof window&&"object"===q(window._swalDefaults)&&He.setDefaults(window._swalDefaults),He));return De.default=De}),"undefined"!=typeof window&&window.Sweetalert2&&(window.Sweetalert2.version="7.33.1",window.swal=window.sweetAlert=window.Swal=window.SweetAlert=window.Sweetalert2);
79494"use strict";
79495// Set defaults
79496swal.mixin({
79497	width: 400,
79498	heightAuto: false,
79499	padding: '2.5rem',
79500	buttonsStyling: false,
79501	confirmButtonClass: 'btn btn-success',
79502	confirmButtonColor: null,
79503	cancelButtonClass: 'btn btn-secondary',
79504	cancelButtonColor: null
79505});
79506var identity = function (x) {
79507    return x;
79508};
79509
79510var isArray = function (value) {
79511    return $.isArray(value);
79512};
79513
79514var isObject = function (value) {
79515    return !isArray(value) && (value instanceof Object);
79516};
79517
79518var isNumber = function (value) {
79519    return value instanceof Number;
79520};
79521
79522var isFunction = function (value) {
79523    return value instanceof Function;
79524};
79525
79526var indexOf = function (object, value) {
79527    return $.inArray(value, object);
79528};
79529
79530var inArray = function (array, value) {
79531    return indexOf(array, value) !== -1;
79532};
79533
79534var foreach = function (collection, callback) {
79535    for(var i in collection) {
79536        if(collection.hasOwnProperty(i)) {
79537            callback(collection[i], i, collection);
79538        }
79539    }
79540};
79541
79542
79543var last = function (array) {
79544    return array[array.length - 1];
79545};
79546
79547var argumentsToArray = function (args) {
79548    return Array.prototype.slice.call(args);
79549};
79550
79551var extend = function () {
79552    var extended = {};
79553    foreach(argumentsToArray(arguments), function (o) {
79554        foreach(o, function (val, key) {
79555            extended[key] = val;
79556        });
79557    });
79558    return extended;
79559};
79560
79561var mapToArray = function (collection, callback) {
79562    var mapped = [];
79563    foreach(collection, function (value, key, coll) {
79564        mapped.push(callback(value, key, coll));
79565    });
79566    return mapped;
79567};
79568
79569var mapToObject = function (collection, callback, keyCallback) {
79570    var mapped = {};
79571    foreach(collection, function (value, key, coll) {
79572        key = keyCallback ? keyCallback(key, value) : key;
79573        mapped[key] = callback(value, key, coll);
79574    });
79575    return mapped;
79576};
79577
79578var map = function (collection, callback, keyCallback) {
79579    return isArray(collection) ?
79580        mapToArray(collection, callback) :
79581        mapToObject(collection, callback, keyCallback);
79582};
79583
79584var pluck = function (arrayOfObjects, key) {
79585    return map(arrayOfObjects, function (val) {
79586        return val[key];
79587    });
79588};
79589
79590var filter = function (collection, callback) {
79591    var filtered;
79592
79593    if(isArray(collection)) {
79594        filtered = [];
79595        foreach(collection, function (val, key, coll) {
79596            if(callback(val, key, coll)) {
79597                filtered.push(val);
79598            }
79599        });
79600    }
79601    else {
79602        filtered = {};
79603        foreach(collection, function (val, key, coll) {
79604            if(callback(val, key, coll)) {
79605                filtered[key] = val;
79606            }
79607        });
79608    }
79609
79610    return filtered;
79611};
79612
79613var call = function (collection, functionName, args) {
79614    return map(collection, function (object, name) {
79615        return object[functionName].apply(object, args || []);
79616    });
79617};
79618
79619//execute callback immediately and at most one time on the minimumInterval,
79620//ignore block attempts
79621var throttle = function (minimumInterval, callback) {
79622    var timeout = null;
79623    return function () {
79624        var that = this, args = arguments;
79625        if(timeout === null) {
79626            timeout = setTimeout(function () {
79627                timeout = null;
79628            }, minimumInterval);
79629            callback.apply(that, args);
79630        }
79631    };
79632};
79633
79634
79635var mixinPubSub = function (object) {
79636    object = object || {};
79637    var topics = {};
79638
79639    object.publish = function (topic, data) {
79640        foreach(topics[topic], function (callback) {
79641            callback(data);
79642        });
79643    };
79644
79645    object.subscribe = function (topic, callback) {
79646        topics[topic] = topics[topic] || [];
79647        topics[topic].push(callback);
79648    };
79649
79650    object.unsubscribe = function (callback) {
79651        foreach(topics, function (subscribers) {
79652            var index = indexOf(subscribers, callback);
79653            if(index !== -1) {
79654                subscribers.splice(index, 1);
79655            }
79656        });
79657    };
79658
79659    return object;
79660};
79661
79662// jquery.input version 0.0.0
79663// https://github.com/DubFriend/jquery.input
79664// (MIT) 09-04-2014
79665// Brian Detering <[email protected]> (http://www.briandetering.net/)
79666(function ($) {
79667'use strict';
79668
79669var createBaseInput = function (fig, my) {
79670    var self = mixinPubSub(),
79671        $self = fig.$;
79672
79673    self.getType = function () {
79674        throw 'implement me (return type. "text", "radio", etc.)';
79675    };
79676
79677    self.$ = function (selector) {
79678        return selector ? $self.find(selector) : $self;
79679    };
79680
79681    self.disable = function () {
79682        self.$().prop('disabled', true);
79683        self.publish('isEnabled', false);
79684    };
79685
79686    self.enable = function () {
79687        self.$().prop('disabled', false);
79688        self.publish('isEnabled', true);
79689    };
79690
79691    my.equalTo = function (a, b) {
79692        return a === b;
79693    };
79694
79695    my.publishChange = (function () {
79696        var oldValue;
79697        return function (e, domElement) {
79698            var newValue = self.get();
79699            if(!my.equalTo(newValue, oldValue)) {
79700                self.publish('change', { e: e, domElement: domElement });
79701            }
79702            oldValue = newValue;
79703        };
79704    }());
79705
79706    return self;
79707};
79708
79709
79710var createInput = function (fig, my) {
79711    var self = createBaseInput(fig, my);
79712
79713    self.get = function () {
79714        return self.$().val();
79715    };
79716
79717    self.set = function (newValue) {
79718        self.$().val(newValue);
79719    };
79720
79721    self.clear = function () {
79722        self.set('');
79723    };
79724
79725    my.buildSetter = function (callback) {
79726        return function (newValue) {
79727            callback.call(self, newValue);
79728        };
79729    };
79730
79731    return self;
79732};
79733
79734var inputEqualToArray = function (a, b) {
79735    a = isArray(a) ? a : [a];
79736    b = isArray(b) ? b : [b];
79737
79738    var isEqual = true;
79739    if(a.length !== b.length) {
79740        isEqual = false;
79741    }
79742    else {
79743        foreach(a, function (value) {
79744            if(!inArray(b, value)) {
79745                isEqual = false;
79746            }
79747        });
79748    }
79749
79750    return isEqual;
79751};
79752
79753var createInputButton = function (fig) {
79754    var my = {},
79755        self = createInput(fig, my);
79756
79757    self.getType = function () {
79758        return 'button';
79759    };
79760
79761    self.$().on('change', function (e) {
79762        my.publishChange(e, this);
79763    });
79764
79765    return self;
79766};
79767
79768var createInputCheckbox = function (fig) {
79769    var my = {},
79770        self = createInput(fig, my);
79771
79772    self.getType = function () {
79773        return 'checkbox';
79774    };
79775
79776    self.get = function () {
79777        var values = [];
79778        self.$().filter(':checked').each(function () {
79779            values.push($(this).val());
79780        });
79781        return values;
79782    };
79783
79784    self.set = function (newValues) {
79785        newValues = isArray(newValues) ? newValues : [newValues];
79786
79787        self.$().each(function () {
79788            $(this).prop('checked', false);
79789        });
79790
79791        foreach(newValues, function (value) {
79792            self.$().filter('[value="' + value + '"]')
79793                .prop('checked', true);
79794        });
79795    };
79796
79797    my.equalTo = inputEqualToArray;
79798
79799    self.$().change(function (e) {
79800        my.publishChange(e, this);
79801    });
79802
79803    return self;
79804};
79805
79806var createInputEmail = function (fig) {
79807    var my = {},
79808        self = createInputText(fig, my);
79809
79810    self.getType = function () {
79811        return 'email';
79812    };
79813
79814    return self;
79815};
79816
79817var createInputFile = function (fig) {
79818    var my = {},
79819        self = createBaseInput(fig, my);
79820
79821    self.getType = function () {
79822        return 'file';
79823    };
79824
79825    self.get = function () {
79826        return last(self.$().val().split('\\'));
79827    };
79828
79829    self.clear = function () {
79830        // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
79831        this.$().each(function () {
79832            $(this).wrap('<form>').closest('form').get(0).reset();
79833            $(this).unwrap();
79834        });
79835    };
79836
79837    self.$().change(function (e) {
79838        my.publishChange(e, this);
79839        // self.publish('change', self);
79840    });
79841
79842    return self;
79843};
79844
79845var createInputHidden = function (fig) {
79846    var my = {},
79847        self = createInput(fig, my);
79848
79849    self.getType = function () {
79850        return 'hidden';
79851    };
79852
79853    self.$().change(function (e) {
79854        my.publishChange(e, this);
79855    });
79856
79857    return self;
79858};
79859var createInputMultipleFile = function (fig) {
79860    var my = {},
79861        self = createBaseInput(fig, my);
79862
79863    self.getType = function () {
79864        return 'file[multiple]';
79865    };
79866
79867    self.get = function () {
79868        // http://stackoverflow.com/questions/14035530/how-to-get-value-of-html-5-multiple-file-upload-variable-using-jquery
79869        var fileListObject = self.$().get(0).files || [],
79870            names = [], i;
79871
79872        for(i = 0; i < (fileListObject.length || 0); i += 1) {
79873            names.push(fileListObject[i].name);
79874        }
79875
79876        return names;
79877    };
79878
79879    self.clear = function () {
79880        // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
79881        this.$().each(function () {
79882            $(this).wrap('<form>').closest('form').get(0).reset();
79883            $(this).unwrap();
79884        });
79885    };
79886
79887    self.$().change(function (e) {
79888        my.publishChange(e, this);
79889    });
79890
79891    return self;
79892};
79893
79894var createInputMultipleSelect = function (fig) {
79895    var my = {},
79896        self = createInput(fig, my);
79897
79898    self.getType = function () {
79899        return 'select[multiple]';
79900    };
79901
79902    self.get = function () {
79903        return self.$().val() || [];
79904    };
79905
79906    self.set = function (newValues) {
79907        self.$().val(
79908            newValues === '' ? [] : isArray(newValues) ? newValues : [newValues]
79909        );
79910    };
79911
79912    my.equalTo = inputEqualToArray;
79913
79914    self.$().change(function (e) {
79915        my.publishChange(e, this);
79916    });
79917
79918    return self;
79919};
79920
79921var createInputPassword = function (fig) {
79922    var my = {},
79923        self = createInputText(fig, my);
79924
79925    self.getType = function () {
79926        return 'password';
79927    };
79928
79929    return self;
79930};
79931
79932var createInputRadio = function (fig) {
79933    var my = {},
79934        self = createInput(fig, my);
79935
79936    self.getType = function () {
79937        return 'radio';
79938    };
79939
79940    self.get = function () {
79941        return self.$().filter(':checked').val() || null;
79942    };
79943
79944    self.set = function (newValue) {
79945        if(!newValue) {
79946            self.$().each(function () {
79947                $(this).prop('checked', false);
79948            });
79949        }
79950        else {
79951            self.$().filter('[value="' + newValue + '"]').prop('checked', true);
79952        }
79953    };
79954
79955    self.$().change(function (e) {
79956        my.publishChange(e, this);
79957    });
79958
79959    return self;
79960};
79961
79962var createInputRange = function (fig) {
79963    var my = {},
79964        self = createInput(fig, my);
79965
79966    self.getType = function () {
79967        return 'range';
79968    };
79969
79970    self.$().change(function (e) {
79971        my.publishChange(e, this);
79972    });
79973
79974    return self;
79975};
79976
79977var createInputSelect = function (fig) {
79978    var my = {},
79979        self = createInput(fig, my);
79980
79981    self.getType = function () {
79982        return 'select';
79983    };
79984
79985    self.$().change(function (e) {
79986        my.publishChange(e, this);
79987    });
79988
79989    return self;
79990};
79991
79992var createInputText = function (fig) {
79993    var my = {},
79994        self = createInput(fig, my);
79995
79996    self.getType = function () {
79997        return 'text';
79998    };
79999
80000    self.$().on('change keyup keydown', function (e) {
80001        my.publishChange(e, this);
80002    });
80003
80004    return self;
80005};
80006
80007var createInputTextarea = function (fig) {
80008    var my = {},
80009        self = createInput(fig, my);
80010
80011    self.getType = function () {
80012        return 'textarea';
80013    };
80014
80015    self.$().on('change keyup keydown', function (e) {
80016        my.publishChange(e, this);
80017    });
80018
80019    return self;
80020};
80021
80022var createInputURL = function (fig) {
80023    var my = {},
80024        self = createInputText(fig, my);
80025
80026    self.getType = function () {
80027        return 'url';
80028    };
80029
80030    return self;
80031};
80032
80033var buildFormInputs = function (fig) {
80034    var inputs = {},
80035        $self = fig.$;
80036
80037    var constructor = fig.constructorOverride || {
80038        button: createInputButton,
80039        text: createInputText,
80040        url: createInputURL,
80041        email: createInputEmail,
80042        password: createInputPassword,
80043        range: createInputRange,
80044        textarea: createInputTextarea,
80045        select: createInputSelect,
80046        'select[multiple]': createInputMultipleSelect,
80047        radio: createInputRadio,
80048        checkbox: createInputCheckbox,
80049        file: createInputFile,
80050        'file[multiple]': createInputMultipleFile,
80051        hidden: createInputHidden
80052    };
80053
80054    var addInputsBasic = function (type, selector) {
80055        var $input = isObject(selector) ? selector : $self.find(selector);
80056
80057        $input.each(function () {
80058            var name = $(this).attr('name');
80059            inputs[name] = constructor[type]({
80060                $: $(this)
80061            });
80062        });
80063    };
80064
80065    var addInputsGroup = function (type, selector) {
80066        var names = [],
80067            $input = isObject(selector) ? selector : $self.find(selector);
80068
80069        if(isObject(selector)) {
80070            inputs[$input.attr('name')] = constructor[type]({
80071                $: $input
80072            });
80073        }
80074        else {
80075            // group by name attribute
80076            $input.each(function () {
80077                if(indexOf(names, $(this).attr('name')) === -1) {
80078                    names.push($(this).attr('name'));
80079                }
80080            });
80081
80082            foreach(names, function (name) {
80083                inputs[name] = constructor[type]({
80084                    $: $self.find('input[name="' + name + '"]')
80085                });
80086            });
80087        }
80088    };
80089
80090
80091    if($self.is('input, select, textarea')) {
80092        if($self.is('input[type="button"], button, input[type="submit"]')) {
80093            addInputsBasic('button', $self);
80094        }
80095        else if($self.is('textarea')) {
80096            addInputsBasic('textarea', $self);
80097        }
80098        else if(
80099            $self.is('input[type="text"]') ||
80100            $self.is('input') && !$self.attr('type')
80101        ) {
80102            addInputsBasic('text', $self);
80103        }
80104        else if($self.is('input[type="password"]')) {
80105            addInputsBasic('password', $self);
80106        }
80107        else if($self.is('input[type="email"]')) {
80108            addInputsBasic('email', $self);
80109        }
80110        else if($self.is('input[type="url"]')) {
80111            addInputsBasic('url', $self);
80112        }
80113        else if($self.is('input[type="range"]')) {
80114            addInputsBasic('range', $self);
80115        }
80116        else if($self.is('select')) {
80117            if($self.is('[multiple]')) {
80118                addInputsBasic('select[multiple]', $self);
80119            }
80120            else {
80121                addInputsBasic('select', $self);
80122            }
80123        }
80124        else if($self.is('input[type="file"]')) {
80125            if($self.is('[multiple]')) {
80126                addInputsBasic('file[multiple]', $self);
80127            }
80128            else {
80129                addInputsBasic('file', $self);
80130            }
80131        }
80132        else if($self.is('input[type="hidden"]')) {
80133            addInputsBasic('hidden', $self);
80134        }
80135        else if($self.is('input[type="radio"]')) {
80136            addInputsGroup('radio', $self);
80137        }
80138        else if($self.is('input[type="checkbox"]')) {
80139            addInputsGroup('checkbox', $self);
80140        }
80141        else {
80142            //in all other cases default to a "text" input interface.
80143            addInputsBasic('text', $self);
80144        }
80145    }
80146    else {
80147        addInputsBasic('button', 'input[type="button"], button, input[type="submit"]');
80148        addInputsBasic('text', 'input[type="text"]');
80149        addInputsBasic('password', 'input[type="password"]');
80150        addInputsBasic('email', 'input[type="email"]');
80151        addInputsBasic('url', 'input[type="url"]');
80152        addInputsBasic('range', 'input[type="range"]');
80153        addInputsBasic('textarea', 'textarea');
80154        addInputsBasic('select', 'select:not([multiple])');
80155        addInputsBasic('select[multiple]', 'select[multiple]');
80156        addInputsBasic('file', 'input[type="file"]:not([multiple])');
80157        addInputsBasic('file[multiple]', 'input[type="file"][multiple]');
80158        addInputsBasic('hidden', 'input[type="hidden"]');
80159        addInputsGroup('radio', 'input[type="radio"]');
80160        addInputsGroup('checkbox', 'input[type="checkbox"]');
80161    }
80162
80163    return inputs;
80164};
80165
80166$.fn.inputVal = function (newValue) {
80167    var $self = $(this);
80168
80169    var inputs = buildFormInputs({ $: $self });
80170
80171    if($self.is('input, textarea, select')) {
80172        if(typeof newValue === 'undefined') {
80173            return inputs[$self.attr('name')].get();
80174        }
80175        else {
80176            inputs[$self.attr('name')].set(newValue);
80177            return $self;
80178        }
80179    }
80180    else {
80181        if(typeof newValue === 'undefined') {
80182            return call(inputs, 'get');
80183        }
80184        else {
80185            foreach(newValue, function (value, inputName) {
80186                inputs[inputName].set(value);
80187            });
80188            return $self;
80189        }
80190    }
80191};
80192
80193$.fn.inputOnChange = function (callback) {
80194    var $self = $(this);
80195    var inputs = buildFormInputs({ $: $self });
80196    foreach(inputs, function (input) {
80197        input.subscribe('change', function (data) {
80198            callback.call(data.domElement, data.e);
80199        });
80200    });
80201    return $self;
80202};
80203
80204$.fn.inputDisable = function () {
80205    var $self = $(this);
80206    call(buildFormInputs({ $: $self }), 'disable');
80207    return $self;
80208};
80209
80210$.fn.inputEnable = function () {
80211    var $self = $(this);
80212    call(buildFormInputs({ $: $self }), 'enable');
80213    return $self;
80214};
80215
80216$.fn.inputClear = function () {
80217    var $self = $(this);
80218    call(buildFormInputs({ $: $self }), 'clear');
80219    return $self;
80220};
80221
80222}(jQuery));
80223
80224$.fn.repeaterVal = function () {
80225    var parse = function (raw) {
80226        var parsed = [];
80227
80228        foreach(raw, function (val, key) {
80229            var parsedKey = [];
80230            if(key !== "undefined") {
80231                parsedKey.push(key.match(/^[^\[]*/)[0]);
80232                parsedKey = parsedKey.concat(map(
80233                    key.match(/\[[^\]]*\]/g),
80234                    function (bracketed) {
80235                        return bracketed.replace(/[\[\]]/g, '');
80236                    }
80237                ));
80238
80239                parsed.push({
80240                    val: val,
80241                    key: parsedKey
80242                });
80243            }
80244        });
80245
80246        return parsed;
80247    };
80248
80249    var build = function (parsed) {
80250        if(
80251            parsed.length === 1 &&
80252            (parsed[0].key.length === 0 || parsed[0].key.length === 1 && !parsed[0].key[0])
80253        ) {
80254            return parsed[0].val;
80255        }
80256
80257        foreach(parsed, function (p) {
80258            p.head = p.key.shift();
80259        });
80260
80261        var grouped = (function () {
80262            var grouped = {};
80263
80264            foreach(parsed, function (p) {
80265                if(!grouped[p.head]) {
80266                    grouped[p.head] = [];
80267                }
80268                grouped[p.head].push(p);
80269            });
80270
80271            return grouped;
80272        }());
80273
80274        var built;
80275
80276        if(/^[0-9]+$/.test(parsed[0].head)) {
80277            built = [];
80278            foreach(grouped, function (group) {
80279                built.push(build(group));
80280            });
80281        }
80282        else {
80283            built = {};
80284            foreach(grouped, function (group, key) {
80285                built[key] = build(group);
80286            });
80287        }
80288
80289        return built;
80290    };
80291
80292    return build(parse($(this).inputVal()));
80293};
80294
80295$.fn.repeater = function (fig) {
80296    fig = fig || {};
80297
80298    var setList;
80299
80300    $(this).each(function () {
80301
80302        var $self = $(this);
80303
80304        var show = fig.show || function () {
80305            $(this).show();
80306        };
80307
80308        var hide = fig.hide || function (removeElement) {
80309            removeElement();
80310        };
80311
80312        var $list = $self.find('[data-repeater-list]').first();
80313
80314        var $filterNested = function ($items, repeaters) {
80315            return $items.filter(function () {
80316                return repeaters ?
80317                    $(this).closest(
80318                        pluck(repeaters, 'selector').join(',')
80319                    ).length === 0 : true;
80320            });
80321        };
80322
80323        var $items = function () {
80324            return $filterNested($list.find('[data-repeater-item]'), fig.repeaters);
80325        };
80326
80327        var $itemTemplate = $list.find('[data-repeater-item]')
80328                                 .first().clone().hide();
80329
80330        var $firstDeleteButton = $filterNested(
80331            $filterNested($(this).find('[data-repeater-item]'), fig.repeaters)
80332            .first().find('[data-repeater-delete]'),
80333            fig.repeaters
80334        );
80335
80336        if(fig.isFirstItemUndeletable && $firstDeleteButton) {
80337            $firstDeleteButton.remove();
80338        }
80339
80340        var getGroupName = function () {
80341            var groupName = $list.data('repeater-list');
80342            return fig.$parent ?
80343                fig.$parent.data('item-name') + '[' + groupName + ']' :
80344                groupName;
80345        };
80346
80347        var initNested = function ($listItems) {
80348            if(fig.repeaters) {
80349                $listItems.each(function () {
80350                    var $item = $(this);
80351                    foreach(fig.repeaters, function (nestedFig) {
80352                        $item.find(nestedFig.selector).repeater(extend(
80353                            nestedFig, { $parent: $item }
80354                        ));
80355                    });
80356                });
80357            }
80358        };
80359
80360        var $foreachRepeaterInItem = function (repeaters, $item, cb) {
80361            if(repeaters) {
80362                foreach(repeaters, function (nestedFig) {
80363                    cb.call($item.find(nestedFig.selector)[0], nestedFig);
80364                });
80365            }
80366        };
80367
80368        var setIndexes = function ($items, groupName, repeaters) {
80369            $items.each(function (index) {
80370                var $item = $(this);
80371                $item.data('item-name', groupName + '[' + index + ']');
80372                $filterNested($item.find('[name]'), repeaters)
80373                .each(function () {
80374                    var $input = $(this);
80375                    // match non empty brackets (ex: "[foo]")
80376                    var matches = $input.attr('name').match(/\[[^\]]+\]/g);
80377
80378                    var name = matches ?
80379                        // strip "[" and "]" characters
80380                        last(matches).replace(/\[|\]/g, '') :
80381                        $input.attr('name');
80382
80383
80384                    var newName = groupName + '[' + index + '][' + name + ']' +
80385                        ($input.is(':checkbox') || $input.attr('multiple') ? '[]' : '');
80386
80387                    $input.attr('name', newName);
80388
80389                    $foreachRepeaterInItem(repeaters, $item, function (nestedFig) {
80390                        var $repeater = $(this);
80391                        setIndexes(
80392                            $filterNested($repeater.find('[data-repeater-item]'), nestedFig.repeaters || []),
80393                            groupName + '[' + index + ']' +
80394                                        '[' + $repeater.find('[data-repeater-list]').first().data('repeater-list') + ']',
80395                            nestedFig.repeaters
80396                        );
80397                    });
80398                });
80399            });
80400
80401            $list.find('input[name][checked]')
80402                .removeAttr('checked')
80403                .prop('checked', true);
80404        };
80405
80406        setIndexes($items(), getGroupName(), fig.repeaters);
80407        initNested($items());
80408        if(fig.initEmpty) {
80409            $items().remove();
80410        }
80411
80412        if(fig.ready) {
80413            fig.ready(function () {
80414                setIndexes($items(), getGroupName(), fig.repeaters);
80415            });
80416        }
80417
80418        var appendItem = (function () {
80419            var setItemsValues = function ($item, data, repeaters) {
80420                if(data || fig.defaultValues) {
80421                    var inputNames = {};
80422                    $filterNested($item.find('[name]'), repeaters).each(function () {
80423                        var key = $(this).attr('name').match(/\[([^\]]*)(\]|\]\[\])$/)[1];
80424                        inputNames[key] = $(this).attr('name');
80425                    });
80426
80427                    $item.inputVal(map(
80428                        filter(data || fig.defaultValues, function (val, name) {
80429                            return inputNames[name];
80430                        }),
80431                        identity,
80432                        function (name) {
80433                            return inputNames[name];
80434                        }
80435                    ));
80436                }
80437
80438
80439                $foreachRepeaterInItem(repeaters, $item, function (nestedFig) {
80440                    var $repeater = $(this);
80441                    $filterNested(
80442                        $repeater.find('[data-repeater-item]'),
80443                        nestedFig.repeaters
80444                    )
80445                    .each(function () {
80446                        var fieldName = $repeater.find('[data-repeater-list]').data('repeater-list');
80447                        if(data && data[fieldName]) {
80448                            var $template = $(this).clone();
80449                            $repeater.find('[data-repeater-item]').remove();
80450                            foreach(data[fieldName], function (data) {
80451                                var $item = $template.clone();
80452                                setItemsValues(
80453                                    $item,
80454                                    data,
80455                                    nestedFig.repeaters || []
80456                                );
80457                                $repeater.find('[data-repeater-list]').append($item);
80458                            });
80459                        }
80460                        else {
80461                            setItemsValues(
80462                                $(this),
80463                                nestedFig.defaultValues,
80464                                nestedFig.repeaters || []
80465                            );
80466                        }
80467                    });
80468                });
80469
80470            };
80471
80472            return function ($item, data) {
80473                $list.append($item);
80474                setIndexes($items(), getGroupName(), fig.repeaters);
80475                $item.find('[name]').each(function () {
80476                    $(this).inputClear();
80477                });
80478                setItemsValues($item, data || fig.defaultValues, fig.repeaters);
80479            };
80480        }());
80481
80482        var addItem = function (data) {
80483            var $item = $itemTemplate.clone();
80484            appendItem($item, data);
80485            if(fig.repeaters) {
80486                initNested($item);
80487            }
80488            show.call($item.get(0));
80489        };
80490
80491        setList = function (rows) {
80492            $items().remove();
80493            foreach(rows, addItem);
80494        };
80495
80496        $filterNested($self.find('[data-repeater-create]'), fig.repeaters).click(function () {
80497            addItem();
80498        });
80499
80500        $list.on('click', '[data-repeater-delete]', function () {
80501            var self = $(this).closest('[data-repeater-item]').get(0);
80502            hide.call(self, function () {
80503                $(self).remove();
80504                setIndexes($items(), getGroupName(), fig.repeaters);
80505            });
80506        });
80507    });
80508
80509    this.setList = setList;
80510
80511    return this;
80512};
80513
80514(function (global, factory) {
80515	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
80516	typeof define === 'function' && define.amd ? define(factory) :
80517	(global.DOMPurify = factory());
80518}(this, (function () { 'use strict';
80519
80520var freeze$1 = Object.freeze || function (x) {
80521  return x;
80522};
80523
80524var html = freeze$1(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
80525
80526// SVG
80527var svg = freeze$1(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']);
80528
80529var svgFilters = freeze$1(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
80530
80531var mathMl = freeze$1(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
80532
80533var text = freeze$1(['#text']);
80534
80535var freeze$2 = Object.freeze || function (x) {
80536  return x;
80537};
80538
80539var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
80540
80541var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', '
80541y1', 'y2', 'z', 'zoomandpan']);
80542
80543var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
80544
80545var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
80546
80547var hasOwnProperty = Object.hasOwnProperty;
80548var setPrototypeOf = Object.setPrototypeOf;
80549
80550var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
80551var apply$1 = _ref$1.apply;
80552
80553if (!apply$1) {
80554  apply$1 = function apply(fun, thisValue, args) {
80555    return fun.apply(thisValue, args);
80556  };
80557}
80558
80559/* Add properties to a lookup table */
80560function addToSet(set, array) {
80561  if (setPrototypeOf) {
80562    // Make 'in' and truthy checks like Boolean(set.constructor)
80563    // independent of any properties defined on Object.prototype.
80564    // Prevent prototype setters from intercepting set as a this value.
80565    setPrototypeOf(set, null);
80566  }
80567
80568  var l = array.length;
80569  while (l--) {
80570    var element = array[l];
80571    if (typeof element === 'string') {
80572      var lcElement = element.toLowerCase();
80573      if (lcElement !== element) {
80574        // Config presets (e.g. tags.js, attrs.js) are immutable.
80575        if (!Object.isFrozen(array)) {
80576          array[l] = lcElement;
80577        }
80578
80579        element = lcElement;
80580      }
80581    }
80582
80583    set[element] = true;
80584  }
80585
80586  return set;
80587}
80588
80589/* Shallow clone an object */
80590function clone(object) {
80591  var newObject = {};
80592
80593  var property = void 0;
80594  for (property in object) {
80595    if (apply$1(hasOwnProperty, object, [property])) {
80596      newObject[property] = object[property];
80597    }
80598  }
80599
80600  return newObject;
80601}
80602
80603var seal = Object.seal || function (x) {
80604  return x;
80605};
80606
80607var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
80608var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
80609var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
80610var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
80611var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
80612);
80613var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
80614var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex
80615);
80616
80617var _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; };
80618
80619function _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); } }
80620
80621var _ref = typeof Reflect !== 'undefined' && Reflect;
80622var apply = _ref.apply;
80623
80624var arraySlice = Array.prototype.slice;
80625var freeze = Object.freeze;
80626
80627var getGlobal = function getGlobal() {
80628  return typeof window === 'undefined' ? null : window;
80629};
80630
80631if (!apply) {
80632  apply = function apply(fun, thisValue, args) {
80633    return fun.apply(thisValue, args);
80634  };
80635}
80636
80637/**
80638 * Creates a no-op policy for internal use only.
80639 * Don't export this function outside this module!
80640 * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
80641 * @param {Document} document The document object (to determine policy name suffix)
80642 * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
80643 * are not supported).
80644 */
80645var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
80646  if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
80647    return null;
80648  }
80649
80650  // Allow the callers to control the unique policy name
80651  // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
80652  // Policy creation with duplicate names throws in Trusted Types.
80653  var suffix = null;
80654  var ATTR_NAME = 'data-tt-policy-suffix';
80655  if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
80656    suffix = document.currentScript.getAttribute(ATTR_NAME);
80657  }
80658
80659  var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
80660
80661  try {
80662    return trustedTypes.createPolicy(policyName, {
80663      createHTML: function createHTML(html$$1) {
80664        return html$$1;
80665      }
80666    });
80667  } catch (error) {
80668    // Policy creation failed (most likely another DOMPurify script has
80669    // already run). Skip creating the policy, as this will only cause errors
80670    // if TT are enforced.
80671    console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
80672    return null;
80673  }
80674};
80675
80676function createDOMPurify() {
80677  var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
80678
80679  var DOMPurify = function DOMPurify(root) {
80680    return createDOMPurify(root);
80681  };
80682
80683  /**
80684   * Version label, exposed for easier checks
80685   * if DOMPurify is up to date or not
80686   */
80687  DOMPurify.version = '1.0.10';
80688
80689  /**
80690   * Array of elements that DOMPurify removed during sanitation.
80691   * Empty if nothing was removed.
80692   */
80693  DOMPurify.removed = [];
80694
80695  if (!window || !window.document || window.document.nodeType !== 9) {
80696    // Not running in a browser, provide a factory function
80697    // so that you can pass your own Window
80698    DOMPurify.isSupported = false;
80699
80700    return DOMPurify;
80701  }
80702
80703  var originalDocument = window.document;
80704  var useDOMParser = false;
80705  var removeTitle = false;
80706
80707  var document = window.document;
80708  var DocumentFragment = window.DocumentFragment,
80709      HTMLTemplateElement = window.HTMLTemplateElement,
80710      Node = window.Node,
80711      NodeFilter = window.NodeFilter,
80712      _window$NamedNodeMap = window.NamedNodeMap,
80713      NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
80714      Text = window.Text,
80715      Comment = window.Comment,
80716      DOMParser = window.DOMParser,
80717      TrustedTypes = window.TrustedTypes;
80718
80719  // As per issue #47, the web-components registry is inherited by a
80720  // new document created via createHTMLDocument. As per the spec
80721  // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
80722  // a new empty registry is used when creating a template contents owner
80723  // document, so we use that as our parent document to ensure nothing
80724  // is inherited.
80725
80726  if (typeof HTMLTemplateElement === 'function') {
80727    var template = document.createElement('template');
80728    if (template.content && template.content.ownerDocument) {
80729      document = template.content.ownerDocument;
80730    }
80731  }
80732
80733  var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
80734  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
80735
80736  var _document = document,
80737      implementation = _document.implementation,
80738      createNodeIterator = _document.createNodeIterator,
80739      getElementsByTagName = _document.getElementsByTagName,
80740      createDocumentFragment = _document.createDocumentFragment;
80741  var importNode = originalDocument.importNode;
80742
80743
80744  var hooks = {};
80745
80746  /**
80747   * Expose whether this browser supports running the full DOMPurify.
80748   */
80749  DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
80750
80751  var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
80752      ERB_EXPR$$1 = ERB_EXPR,
80753      DATA_ATTR$$1 = DATA_ATTR,
80754      ARIA_ATTR$$1 = ARIA_ATTR,
80755      IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
80756      ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
80757  var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
80758  /**
80759   * We consider the elements and attributes below to be safe. Ideally
80760   * don't add any new ones but feel free to remove unwanted ones.
80761   */
80762
80763  /* allowed element names */
80764
80765  var ALLOWED_TAGS = null;
80766  var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));
80767
80768  /* Allowed attribute names */
80769  var ALLOWED_ATTR = null;
80770  var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));
80771
80772  /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
80773  var FORBID_TAGS = null;
80774
80775  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
80776  var FORBID_ATTR = null;
80777
80778  /* Decide if ARIA attributes are okay */
80779  var ALLOW_ARIA_ATTR = true;
80780
80781  /* Decide if custom data attributes are okay */
80782  var ALLOW_DATA_ATTR = true;
80783
80784  /* Decide if unknown protocols are okay */
80785  var ALLOW_UNKNOWN_PROTOCOLS = false;
80786
80787  /* Output should be safe for jQuery's $() factory? */
80788  var SAFE_FOR_JQUERY = false;
80789
80790  /* Output should be safe for common template engines.
80791   * This means, DOMPurify removes data attributes, mustaches and ERB
80792   */
80793  var SAFE_FOR_TEMPLATES = false;
80794
80795  /* Decide if document with <html>... should be returned */
80796  var WHOLE_DOCUMENT = false;
80797
80798  /* Track whether config is already set on this instance of DOMPurify. */
80799  var SET_CONFIG = false;
80800
80801  /* Decide if all elements (e.g. style, script) must be children of
80802   * document.body. By default, browsers might move them to document.head */
80803  var FORCE_BODY = false;
80804
80805  /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
80806   * string (or a TrustedHTML object if Trusted Types are supported).
80807   * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
80808   */
80809  var RETURN_DOM = false;
80810
80811  /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
80812   * string  (or a TrustedHTML object if Trusted Types are supported) */
80813  var RETURN_DOM_FRAGMENT = false;
80814
80815  /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
80816   * `Node` is imported into the current `Document`. If this flag is not enabled the
80817   * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
80818   * DOMPurify. */
80819  var RETURN_DOM_IMPORT = false;
80820
80821  /* Output should be free from DOM clobbering attacks? */
80822  var SANITIZE_DOM = true;
80823
80824  /* Keep element content when removing element? */
80825  var KEEP_CONTENT = true;
80826
80827  /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
80828   * of importing it into a new Document and returning a sanitized copy */
80829  var IN_PLACE = false;
80830
80831  /* Allow usage of profiles like html, svg and mathMl */
80832  var USE_PROFILES = {};
80833
80834  /* Tags to ignore content of when KEEP_CONTENT is true */
80835  var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);
80836
80837  /* Tags that are safe for data: URIs */
80838  var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
80839
80840  /* Attributes safe for values like "javascript:" */
80841  var URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
80842
80843  /* Keep a reference to config to pass to hooks */
80844  var CONFIG = null;
80845
80846  /* Ideally, do not touch anything below this line */
80847  /* ______________________________________________ */
80848
80849  var formElement = document.createElement('form');
80850
80851  /**
80852   * _parseConfig
80853   *
80854   * @param  {Object} cfg optional config literal
80855   */
80856  // eslint-disable-next-line complexity
80857  var _parseConfig = function _parseConfig(cfg) {
80858    if (CONFIG && CONFIG === cfg) {
80859      return;
80860    }
80861
80862    /* Shield configuration object from tampering */
80863    if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
80864      cfg = {};
80865    }
80866
80867    /* Set configuration parameters */
80868    ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
80869    ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
80870    FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
80871    FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
80872    USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
80873    ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
80874    ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
80875    ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
80876    SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
80877    SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
80878    WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
80879    RETURN_DOM = cfg.RETURN_DOM || false; // Default false
80880    RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
80881    RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
80882    FORCE_BODY = cfg.FORCE_BODY || false; // Default false
80883    SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
80884    KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
80885    IN_PLACE = cfg.IN_PLACE || false; // Default false
80886
80887    IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
80888
80889    if (SAFE_FOR_TEMPLATES) {
80890      ALLOW_DATA_ATTR = false;
80891    }
80892
80893    if (RETURN_DOM_FRAGMENT) {
80894      RETURN_DOM = true;
80895    }
80896
80897    /* Parse profile info */
80898    if (USE_PROFILES) {
80899      ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
80900      ALLOWED_ATTR = [];
80901      if (USE_PROFILES.html === true) {
80902        addToSet(ALLOWED_TAGS, html);
80903        addToSet(ALLOWED_ATTR, html$1);
80904      }
80905
80906      if (USE_PROFILES.svg === true) {
80907        addToSet(ALLOWED_TAGS, svg);
80908        addToSet(ALLOWED_ATTR, svg$1);
80909        addToSet(ALLOWED_ATTR, xml);
80910      }
80911
80912      if (USE_PROFILES.svgFilters === true) {
80913        addToSet(ALLOWED_TAGS, svgFilters);
80914        addToSet(ALLOWED_ATTR, svg$1);
80915        addToSet(ALLOWED_ATTR, xml);
80916      }
80917
80918      if (USE_PROFILES.mathMl === true) {
80919        addToSet(ALLOWED_TAGS, mathMl);
80920        addToSet(ALLOWED_ATTR, mathMl$1);
80921        addToSet(ALLOWED_ATTR, xml);
80922      }
80923    }
80924
80925    /* Merge configuration parameters */
80926    if (cfg.ADD_TAGS) {
80927      if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
80928        ALLOWED_TAGS = clone(ALLOWED_TAGS);
80929      }
80930
80931      addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
80932    }
80933
80934    if (cfg.ADD_ATTR) {
80935      if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
80936        ALLOWED_ATTR = clone(ALLOWED_ATTR);
80937      }
80938
80939      addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
80940    }
80941
80942    if (cfg.ADD_URI_SAFE_ATTR) {
80943      addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
80944    }
80945
80946    /* Add #text in case KEEP_CONTENT is set to true */
80947    if (KEEP_CONTENT) {
80948      ALLOWED_TAGS['#text'] = true;
80949    }
80950
80951    /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
80952    if (WHOLE_DOCUMENT) {
80953      addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
80954    }
80955
80956    /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */
80957    if (ALLOWED_TAGS.table) {
80958      addToSet(ALLOWED_TAGS, ['tbody']);
80959    }
80960
80961    // Prevent further manipulation of configuration.
80962    // Not available in IE8, Safari 5, etc.
80963    if (freeze) {
80964      freeze(cfg);
80965    }
80966
80967    CONFIG = cfg;
80968  };
80969
80970  /**
80971   * _forceRemove
80972   *
80973   * @param  {Node} node a DOM node
80974   */
80975  var _forceRemove = function _forceRemove(node) {
80976    DOMPurify.removed.push({ element: node });
80977    try {
80978      node.parentNode.removeChild(node);
80979    } catch (error) {
80980      node.outerHTML = emptyHTML;
80981    }
80982  };
80983
80984  /**
80985   * _removeAttribute
80986   *
80987   * @param  {String} name an Attribute name
80988   * @param  {Node} node a DOM node
80989   */
80990  var _removeAttribute = function _removeAttribute(name, node) {
80991    try {
80992      DOMPurify.removed.push({
80993        attribute: node.getAttributeNode(name),
80994        from: node
80995      });
80996    } catch (error) {
80997      DOMPurify.removed.push({
80998        attribute: null,
80999        from: node
81000      });
81001    }
81002
81003    node.removeAttribute(name);
81004  };
81005
81006  /**
81007   * _initDocument
81008   *
81009   * @param  {String} dirty a string of dirty markup
81010   * @return {Document} a DOM, filled with the dirty markup
81011   */
81012  var _initDocument = function _initDocument(dirty) {
81013    /* Create a HTML document */
81014    var doc = void 0;
81015    var leadingWhitespace = void 0;
81016
81017    if (FORCE_BODY) {
81018      dirty = '<remove></remove>' + dirty;
81019    } else {
81020      /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
81021      var matches = dirty.match(/^[\s]+/);
81022      leadingWhitespace = matches && matches[0];
81023      if (leadingWhitespace) {
81024        dirty = dirty.slice(leadingWhitespace.length);
81025      }
81026    }
81027
81028    /* Use DOMParser to workaround Firefox bug (see comment below) */
81029    if (useDOMParser) {
81030      try {
81031        doc = new DOMParser().parseFromString(dirty, 'text/html');
81032      } catch (error) {}
81033    }
81034
81035    /* Remove title to fix a mXSS bug in older MS Edge */
81036    if (removeTitle) {
81037      addToSet(FORBID_TAGS, ['title']);
81038    }
81039
81040    /* Otherwise use createHTMLDocument, because DOMParser is unsafe in
81041    Safari (see comment below) */
81042    if (!doc || !doc.documentElement) {
81043      doc = implementation.createHTMLDocument('');
81044      var _doc = doc,
81045          body = _doc.body;
81046
81047      body.parentNode.removeChild(body.parentNode.firstElementChild);
81048      body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
81049    }
81050
81051    if (leadingWhitespace) {
81052      doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
81053    }
81054
81055    /* Work on whole document or just its body */
81056    return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
81057  };
81058
81059  // Firefox uses a different parser for innerHTML rather than
81060  // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)
81061  // which means that you *must* use DOMParser, otherwise the output may
81062  // not be safe if used in a document.write context later.
81063  //
81064  // So we feature detect the Firefox bug and use the DOMParser if necessary.
81065  //
81066  // MS Edge, in older versions, is affected by an mXSS behavior. The second
81067  // check tests for the behavior and fixes it if necessary.
81068  if (DOMPurify.isSupported) {
81069    (function () {
81070      try {
81071        var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">');
81072        if (doc.querySelector('svg img')) {
81073          useDOMParser = true;
81074        }
81075      } catch (error) {}
81076    })();
81077
81078    (function () {
81079      try {
81080        var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
81081        if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
81082          removeTitle = true;
81083        }
81084      } catch (error) {}
81085    })();
81086  }
81087
81088  /**
81089   * _createIterator
81090   *
81091   * @param  {Document} root document/fragment to create iterator for
81092   * @return {Iterator} iterator instance
81093   */
81094  var _createIterator = function _createIterator(root) {
81095    return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
81096      return NodeFilter.FILTER_ACCEPT;
81097    }, false);
81098  };
81099
81100  /**
81101   * _isClobbered
81102   *
81103   * @param  {Node} elm element to check for clobbering attacks
81104   * @return {Boolean} true if clobbered, false if safe
81105   */
81106  var _isClobbered = function _isClobbered(elm) {
81107    if (elm instanceof Text || elm instanceof Comment) {
81108      return false;
81109    }
81110
81111    if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') {
81112      return true;
81113    }
81114
81115    return false;
81116  };
81117
81118  /**
81119   * _isNode
81120   *
81121   * @param  {Node} obj object to check whether it's a DOM node
81122   * @return {Boolean} true is object is a DOM node
81123   */
81124  var _isNode = function _isNode(obj) {
81125    return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';
81126  };
81127
81128  /**
81129   * _executeHook
81130   * Execute user configurable hooks
81131   *
81132   * @param  {String} entryPoint  Name of the hook's entry point
81133   * @param  {Node} currentNode node to work on with the hook
81134   * @param  {Object} data additional hook parameters
81135   */
81136  var _executeHook = function _executeHook(entryPoint, currentNode, data) {
81137    if (!hooks[entryPoint]) {
81138      return;
81139    }
81140
81141    hooks[entryPoint].forEach(function (hook) {
81142      hook.call(DOMPurify, currentNode, data, CONFIG);
81143    });
81144  };
81145
81146  /**
81147   * _sanitizeElements
81148   *
81149   * @protect nodeName
81150   * @protect textContent
81151   * @protect removeChild
81152   *
81153   * @param   {Node} currentNode to check for permission to exist
81154   * @return  {Boolean} true if node was killed, false if left alive
81155   */
81156  // eslint-disable-next-line complexity
81157  var _sanitizeElements = function _sanitizeElements(currentNode) {
81158    var content = void 0;
81159
81160    /* Execute a hook if present */
81161    _executeHook('beforeSanitizeElements', currentNode, null);
81162
81163    /* Check if element is clobbered or can clobber */
81164    if (_isClobbered(currentNode)) {
81165      _forceRemove(currentNode);
81166      return true;
81167    }
81168
81169    /* Now let's check the element's type and name */
81170    var tagName = currentNode.nodeName.toLowerCase();
81171
81172    /* Execute a hook if present */
81173    _executeHook('uponSanitizeElement', currentNode, {
81174      tagName: tagName,
81175      allowedTags: ALLOWED_TAGS
81176    });
81177
81178    /* Remove element if anything forbids its presence */
81179    if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
81180      /* Keep content except for black-listed elements */
81181      if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
81182        try {
81183          var htmlToInsert = currentNode.innerHTML;
81184          currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
81185        } catch (error) {}
81186      }
81187
81188      _forceRemove(currentNode);
81189      return true;
81190    }
81191
81192    /* Remove in case a noscript/noembed XSS is suspected */
81193    if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
81194      _forceRemove(currentNode);
81195      return true;
81196    }
81197
81198    if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
81199      _forceRemove(currentNode);
81200      return true;
81201    }
81202
81203    /* Convert markup to cover jQuery behavior */
81204    if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
81205      DOMPurify.removed.push({ element: currentNode.cloneNode() });
81206      if (currentNode.innerHTML) {
81207        currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
81208      } else {
81209        currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
81210      }
81211    }
81212
81213    /* Sanitize element content to be template-safe */
81214    if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
81215      /* Get the element's text content */
81216      content = currentNode.textContent;
81217      content = content.replace(MUSTACHE_EXPR$$1, ' ');
81218      content = content.replace(ERB_EXPR$$1, ' ');
81219      if (currentNode.textContent !== content) {
81220        DOMPurify.removed.push({ element: currentNode.cloneNode() });
81221        currentNode.textContent = content;
81222      }
81223    }
81224
81225    /* Execute a hook if present */
81226    _executeHook('afterSanitizeElements', currentNode, null);
81227
81228    return false;
81229  };
81230
81231  /**
81232   * _isValidAttribute
81233   *
81234   * @param  {string} lcTag Lowercase tag name of containing element.
81235   * @param  {string} lcName Lowercase attribute name.
81236   * @param  {string} value Attribute value.
81237   * @return {Boolean} Returns true if `value` is valid, otherwise false.
81238   */
81239  // eslint-disable-next-line complexity
81240  var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
81241    /* Make sure attribute cannot clobber */
81242    if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
81243      return false;
81244    }
81245
81246    /* Allow valid data-* attributes: At least one character after "-"
81247        (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
81248        XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
81249        We don't need to check the value; it's always URI safe. */
81250    if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
81251      // This attribute is safe
81252    } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
81253      // This attribute is safe
81254      /* Otherwise, check the name is permitted */
81255    } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
81256      return false;
81257
81258      /* Check value is safe. First, is attr inert? If so, is safe */
81259    } else if (URI_SAFE_ATTRIBUTES[lcName]) {
81260      // This attribute is safe
81261      /* Check no script, data or unknown possibly unsafe URI
81262        unless we know URI values are safe for that attribute */
81263    } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
81264      // This attribute is safe
81265      /* Keep image data URIs alive if src/xlink:href is allowed */
81266      /* Further prevent gadget XSS for dynamically built script tags */
81267    } else if ((lcName === 'src' || lcName === 'xlink:href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
81268      // This attribute is safe
81269      /* Allow unknown protocols: This provides support for links that
81270        are handled by protocol handlers which may be unknown ahead of
81271        time, e.g. fb:, spotify: */
81272    } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
81273      // This attribute is safe
81274      /* Check for binary attributes */
81275      // eslint-disable-next-line no-negated-condition
81276    } else if (!value) {
81277      // Binary attributes are safe at this point
81278      /* Anything else, presume unsafe, do not add it back */
81279    } else {
81280      return false;
81281    }
81282
81283    return true;
81284  };
81285
81286  /**
81287   * _sanitizeAttributes
81288   *
81289   * @protect attributes
81290   * @protect nodeName
81291   * @protect removeAttribute
81292   * @protect setAttribute
81293   *
81294   * @param  {Node} currentNode to sanitize
81295   */
81296  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
81297    var attr = void 0;
81298    var value = void 0;
81299    var lcName = void 0;
81300    var idAttr = void 0;
81301    var l = void 0;
81302    /* Execute a hook if present */
81303    _executeHook('beforeSanitizeAttributes', currentNode, null);
81304
81305    var attributes = currentNode.attributes;
81306
81307    /* Check if we have attributes; if not we might have a text node */
81308
81309    if (!attributes) {
81310      return;
81311    }
81312
81313    var hookEvent = {
81314      attrName: '',
81315      attrValue: '',
81316      keepAttr: true,
81317      allowedAttributes: ALLOWED_ATTR
81318    };
81319    l = attributes.length;
81320
81321    /* Go backwards over all attributes; safely remove bad ones */
81322    while (l--) {
81323      attr = attributes[l];
81324      var _attr = attr,
81325          name = _attr.name,
81326          namespaceURI = _attr.namespaceURI;
81327
81328      value = attr.value.trim();
81329      lcName = name.toLowerCase();
81330
81331      /* Execute a hook if present */
81332      hookEvent.attrName = lcName;
81333      hookEvent.attrValue = value;
81334      hookEvent.keepAttr = true;
81335      _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
81336      value = hookEvent.attrValue;
81337
81338      /* Remove attribute */
81339      // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
81340      // remove a "name" attribute from an <img> tag that has an "id"
81341      // attribute at the time.
81342      if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
81343        idAttr = attributes.id;
81344        attributes = apply(arraySlice, attributes, []);
81345        _removeAttribute('id', currentNode);
81346        _removeAttribute(name, currentNode);
81347        if (attributes.indexOf(idAttr) > l) {
81348          currentNode.setAttribute('id', idAttr.value);
81349        }
81350      } else if (
81351      // This works around a bug in Safari, where input[type=file]
81352      // cannot be dynamically set after type has been removed
81353      currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
81354        continue;
81355      } else {
81356        // This avoids a crash in Safari v9.0 with double-ids.
81357        // The trick is to first set the id to be empty and then to
81358        // remove the attribute
81359        if (name === 'id') {
81360          currentNode.setAttribute(name, '');
81361        }
81362
81363        _removeAttribute(name, currentNode);
81364      }
81365
81366      /* Did the hooks approve of the attribute? */
81367      if (!hookEvent.keepAttr) {
81368        continue;
81369      }
81370
81371      /* Sanitize attribute content to be template-safe */
81372      if (SAFE_FOR_TEMPLATES) {
81373        value = value.replace(MUSTACHE_EXPR$$1, ' ');
81374        value = value.replace(ERB_EXPR$$1, ' ');
81375      }
81376
81377      /* Is `value` valid for this attribute? */
81378      var lcTag = currentNode.nodeName.toLowerCase();
81379      if (!_isValidAttribute(lcTag, lcName, value)) {
81380        continue;
81381      }
81382
81383      /* Handle invalid data-* attribute set by try-catching it */
vendor: 4,719 bytes, lines 81384-81535
81384      try {
81385        if (namespaceURI) {
81386          currentNode.setAttributeNS(namespaceURI, name, value);
81387        } else {
81388          /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
81389          currentNode.setAttribute(name, value);
81390        }
81391
81392        DOMPurify.removed.pop();
81393      } catch (error) {}
81394    }
81395
81396    /* Execute a hook if present */
81397    _executeHook('afterSanitizeAttributes', currentNode, null);
81398  };
81399
81400  /**
81401   * _sanitizeShadowDOM
81402   *
81403   * @param  {DocumentFragment} fragment to iterate over recursively
81404   */
81405  var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
81406    var shadowNode = void 0;
81407    var shadowIterator = _createIterator(fragment);
81408
81409    /* Execute a hook if present */
81410    _executeHook('beforeSanitizeShadowDOM', fragment, null);
81411
81412    while (shadowNode = shadowIterator.nextNode()) {
81413      /* Execute a hook if present */
81414      _executeHook('uponSanitizeShadowNode', shadowNode, null);
81415
81416      /* Sanitize tags and elements */
81417      if (_sanitizeElements(shadowNode)) {
81418        continue;
81419      }
81420
81421      /* Deep shadow DOM detected */
81422      if (shadowNode.content instanceof DocumentFragment) {
81423        _sanitizeShadowDOM(shadowNode.content);
81424      }
81425
81426      /* Check attributes, sanitize if necessary */
81427      _sanitizeAttributes(shadowNode);
81428    }
81429
81430    /* Execute a hook if present */
81431    _executeHook('afterSanitizeShadowDOM', fragment, null);
81432  };
81433
81434  /**
81435   * Sanitize
81436   * Public method providing core sanitation functionality
81437   *
81438   * @param {String|Node} dirty string or DOM node
81439   * @param {Object} configuration object
81440   */
81441  // eslint-disable-next-line complexity
81442  DOMPurify.sanitize = function (dirty, cfg) {
81443    var body = void 0;
81444    var importedNode = void 0;
81445    var currentNode = void 0;
81446    var oldNode = void 0;
81447    var returnNode = void 0;
81448    /* Make sure we have a string to sanitize.
81449      DO NOT return early, as this will return the wrong type if
81450      the user has requested a DOM object rather than a string */
81451    if (!dirty) {
81452      dirty = '<!-->';
81453    }
81454
81455    /* Stringify, in case dirty is an object */
81456    if (typeof dirty !== 'string' && !_isNode(dirty)) {
81457      // eslint-disable-next-line no-negated-condition
81458      if (typeof dirty.toString !== 'function') {
81459        throw new TypeError('toString is not a function');
81460      } else {
81461        dirty = dirty.toString();
81462        if (typeof dirty !== 'string') {
81463          throw new TypeError('dirty is not a string, aborting');
81464        }
81465      }
81466    }
81467
81468    /* Check we can run. Otherwise fall back or ignore */
81469    if (!DOMPurify.isSupported) {
81470      if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
81471        if (typeof dirty === 'string') {
81472          return window.toStaticHTML(dirty);
81473        }
81474
81475        if (_isNode(dirty)) {
81476          return window.toStaticHTML(dirty.outerHTML);
81477        }
81478      }
81479
81480      return dirty;
81481    }
81482
81483    /* Assign config vars */
81484    if (!SET_CONFIG) {
81485      _parseConfig(cfg);
81486    }
81487
81488    /* Clean up removed elements */
81489    DOMPurify.removed = [];
81490
81491    if (IN_PLACE) {
81492      /* No special handling necessary for in-place sanitization */
81493    } else if (dirty instanceof Node) {
81494      /* If dirty is a DOM element, append to an empty document to avoid
81495         elements being stripped by the parser */
81496      body = _initDocument('<!-->');
81497      importedNode = body.ownerDocument.importNode(dirty, true);
81498      if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
81499        /* Node is already a body, use as is */
81500        body = importedNode;
81501      } else {
81502        // eslint-disable-next-line unicorn/prefer-node-append
81503        body.appendChild(importedNode);
81504      }
81505    } else {
81506      /* Exit directly if we have nothing to do */
81507      if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
81508        return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
81509      }
81510
81511      /* Initialize the document to work on */
81512      body = _initDocument(dirty);
81513
81514      /* Check we have a DOM node from the data */
81515      if (!body) {
81516        return RETURN_DOM ? null : emptyHTML;
81517      }
81518    }
81519
81520    /* Remove first element node (ours) if FORCE_BODY is set */
81521    if (body && FORCE_BODY) {
81522      _forceRemove(body.firstChild);
81523    }
81524
81525    /* Get node iterator */
81526    var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
81527
81528    /* Now start iterating over the created document */
81529    while (currentNode = nodeIterator.nextNode()) {
81530      /* Fix IE's strange behavior with manipulated textNodes #89 */
81531      if (currentNode.nodeType === 3 && currentNode === oldNode) {
81532        continue;
81533      }
81534
81535      /* Sanitize tags and elements */
81536      if (_sanitizeElements(currentNode)) {
81537        continue;
81538      }
81539
81540      /* Shadow DOM detected, sanitize it */
81541      if (currentNode.content instanceof DocumentFragment) {
81542        _sanitizeShadowDOM(currentNode.content);
81543      }
81544
81545      /* Check attributes, sanitize if necessary */
81546      _sanitizeAttributes(currentNode);
81547
81548      oldNode = currentNode;
81549    }
81550
81551    oldNode = null;
81552
81553    /* If we sanitized `dirty` in-place, return it. */
81554    if (IN_PLACE) {
81555      return dirty;
81556    }
81557
81558    /* Return sanitized string or DOM */
81559    if (RETURN_DOM) {
81560      if (RETURN_DOM_FRAGMENT) {
81561        returnNode = createDocumentFragment.call(body.ownerDocument);
81562
81563        while (body.firstChild) {
81564          // eslint-disable-next-line unicorn/prefer-node-append
81565          returnNode.appendChild(body.firstChild);
81566        }
81567      } else {
81568        returnNode = body;
81569      }
81570
81571      if (RETURN_DOM_IMPORT) {
81572        /* AdoptNode() is not used because internal state is not reset
81573               (e.g. the past names map of a HTMLFormElement), this is safe
81574               in theory but we would rather not risk another attack vector.
81575               The state that is cloned by importNode() is explicitly defined
81576               by the specs. */
81577        returnNode = importNode.call(originalDocument, returnNode, true);
81578      }
81579
81580      return returnNode;
81581    }
81582
81583    var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
81584
81585    /* Sanitize final string template-safe */
81586    if (SAFE_FOR_TEMPLATES) {
81587      serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
81588      serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
81589    }
81590
81591    return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
81592  };
81593
81594  /**
81595   * Public method to set the configuration once
81596   * setConfig
81597   *
81598   * @param {Object} cfg configuration object
81599   */
81600  DOMPurify.setConfig = function (cfg) {
81601    _parseConfig(cfg);
81602    SET_CONFIG = true;
81603  };
81604
81605  /**
81606   * Public method to remove the configuration
81607   * clearConfig
81608   *
81609   */
81610  DOMPurify.clearConfig = function () {
81611    CONFIG = null;
81612    SET_CONFIG = false;
81613  };
81614
81615  /**
81616   * Public method to check if an attribute value is valid.
81617   * Uses last set config, if any. Otherwise, uses config defaults.
81618   * isValidAttribute
81619   *
81620   * @param  {string} tag Tag name of containing element.
81621   * @param  {string} attr Attribute name.
81622   * @param  {string} value Attribute value.
81623   * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
81624   */
81625  DOMPurify.isValidAttribute = function (tag, attr, value) {
81626    /* Initialize shared config vars if necessary. */
81627    if (!CONFIG) {
81628      _parseConfig({});
81629    }
81630
81631    var lcTag = tag.toLowerCase();
81632    var lcName = attr.toLowerCase();
81633    return _isValidAttribute(lcTag, lcName, value);
81634  };
81635
81636  /**
81637   * AddHook
81638   * Public method to add DOMPurify hooks
81639   *
81640   * @param {String} entryPoint entry point for the hook to add
81641   * @param {Function} hookFunction function to execute
81642   */
81643  DOMPurify.addHook = function (entryPoint, hookFunction) {
81644    if (typeof hookFunction !== 'function') {
81645      return;
81646    }
81647
81648    hooks[entryPoint] = hooks[entryPoint] || [];
81649    hooks[entryPoint].push(hookFunction);
81650  };
81651
81652  /**
81653   * RemoveHook
81654   * Public method to remove a DOMPurify hook at a given entryPoint
81655   * (pops it from the stack of hooks if more are present)
81656   *
81657   * @param {String} entryPoint entry point for the hook to remove
81658   */
81659  DOMPurify.removeHook = function (entryPoint) {
81660    if (hooks[entryPoint]) {
81661      hooks[entryPoint].pop();
81662    }
81663  };
81664
81665  /**
81666   * RemoveHooks
81667   * Public method to remove all DOMPurify hooks at a given entryPoint
81668   *
81669   * @param  {String} entryPoint entry point for the hooks to remove
81670   */
81671  DOMPurify.removeHooks = function (entryPoint) {
81672    if (hooks[entryPoint]) {
81673      hooks[entryPoint] = [];
81674    }
81675  };
81676
81677  /**
81678   * RemoveAllHooks
81679   * Public method to remove all DOMPurify hooks
81680   *
81681   */
81682  DOMPurify.removeAllHooks = function () {
81683    hooks = {};
81684  };
81685
81686  return DOMPurify;
81687}
81688
81689var purify = createDOMPurify();
81690
81691return purify;
81692
81693})));
81694//# sourceMappingURL=purify.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.